Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

Linux I/O port programming mini-HOWTO
Пред.След.

Использование портов ввода/вывода в программах на C

Стандартный способ

Процедуры доступа к портам ввода/выводы находятся в /usr/include/asm/io.h (или в linux/include/asm-i386/io.h в некоторых дистрибутивах ядра). Процедуры представляют собой встроенные (inline) макроопределения, так что вам не нужны никакие библиотеки, и достаточно просто добавить #include <asm/io.h>.

Из-за ограничения в gcc (присутствующего, как минимум, в версии 2.7.2.3 и ниже) и в egcs (всех версий), вы должны компилировать любые исходные тексты, использующие эти процедуры, с включенной оптимизацией (gcc -O1 или выше), или же определить пустое #define extern перед #include <asm/io.h>..

Для отладки вы можете использовать gcc -g -O (по крайней мере, с современными версиями gcc), хотя оптимизация может привести к немного странному поведению отладчика. Если это вам мешает, поместите подпрограммы, работающие с портами ввода/вывода, в отдельный файл и компилируйте с оптимизацией только его.

Перед тем, как вы получите доступ к какому-нибудь порту, вы должны дать вашей программе права на это. Это выполняется, при помощи функции ioperm(from, num, turn_on) (определенной в unistd.h и находящейся в ядре), где from это первый порт, а num это количество подряд идущих портов, которым нужно дать доступ. Например, ioperm(0x300, 5, 1) дает доступ к порту с 0x300 по 0x304 (всего 5 портов). Последний аргумент - это двоичное значение, определяющее, дать ли доступ к портам (истина (1)) или запретить его (ложь (0)). Для включения портов, идущих не подряд, вы можете вызывать ioperm() несколько раз. Для дополнительной информации читайте руководство ioperm(2).

Для вызова ioperm() необходимо иметь права root; таким образом, вы должны запускать программу от пользователя root или установить на файл флаг setuid. После того, как определен доступ к портам, права суперпользователя больше вам не нужны. Вам не нужно непосредственно освобождать порты при помощи ioperm(..., 0), т.к. это делается автоматически, когда программа заканчивает работу.

Выполнение setuid() для переключения на другого пользователя не отключает доступ к портам, данный ioperm(), но это происходит при fork (наследованный процесс теряет доступ, когда как у порождающего процесса он остается).

ioperm() может дать доступ только к портам с 0x000 по 0x3ff; для других портов вам нужно использовать iopl() (который дает доступ ко всем портам сразу). Используйте уровень 3 (iopl(3)), чтобы дать доступ вашей программе ко всем портам ввода/вывода (но будьте осторожны --- доступ к неправильным портам может сделать некоторые нехорошие вещи с вашим компьютером). Опять таки, вам необходимы привилегии root. Дополнительно читайте руководство iopl(2).

Теперь собственно о доступе к портам: Чтобы считать байт (8 бит) из порта, вызовите функцию inb(port), возвращающую считанный байт. Чтобы вывести байт в порт, вызовите процедуру outb(value, port) (обратите внимание на порядок аргументов). Чтобы считать компьютерное слово (16 бит) из портов x и x+1 (по одному байту из каждого образуют слово), вызовите функцию inw(x). Чтобы вывести слово в два порта, используйте outw(value, x). Если вы не уверены, работать с одинарным или двойным портом, вам, скорее всего, нужны inb() и outb(), т.к. порты большинства устройств имеют однобайтный доступ. Также замечу, что все функции, работающие с портами, требуют, как минимум, около микросекунды для выполнения.

Макросы inb_p(), outb_p(), inw_p() и outw_p() работают аналогично вышеуказанным, но добавляют короткую (около микросекунды) задержку после доступа к порту; вы можете установить задержку около четырех микросекунд при помощи #define REALLY_SLOW_IO перед #include <asm/io.h>. Обычно эти макросы (за исключением случаев с #define SLOW_IO_BY_JUMPING, при которых выполнение становится менее точным) используют вывод в порт 0x80 в качестве задержки, так что вам необходимо сначала дать доступ к порту 0x80, при помощи ioperm() (вывод в порт 0x80 никак не влияет на систему). О других способах задержки см. руководства.

См. руководства по ioperm(2), iopl(2) и вышеуказанных макросах.

Альтернативный способ: /dev/port

Другой путь доступа к портам ввода/вывода лежит через открытие файла /dev/port (символьное устройство - major 1, minor 4) на чтение и/или запись (функции f*() из stdio.h работают через буфер, поэтому избегайте их). Затем выполняем lseek() на необходимый байт в файле (позиция файла 0 = порт 0x00, позиция файла 1 = порт 0x01, и т.д.), и считываем/записываем байт или слово при помощи read() или write().

Естественно, для работы программы вам нужен доступ на чтение/запись к файлу /dev/port. Этот способ конечно медленней, чем стандартный, но не требует ни оптимизации при компиляции, ни ioperm(). Кроме того, если вы дадите доступ соответствующим пользователю/группе к файлу /dev/port, вашей программе не нужны права root --- впрочем, это не очень хорошая вещь с точки зрения безопасности, поскольку это может нарушить работу системы путем получения прав root через доступ к диску, сетевой плате и т.д. напрямую.


Пред.НачалоСлед.
Linux I/O port programming mini-HOWTO Доступ к прерываниям (IRQ) и DMA
VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...