ioctl
Эта статья включает список общих ссылок , но в ней отсутствуют достаточные соответствующие встроенные цитаты . ( февраль 2010 г. ) |
В вычислениях , ioctl
(аббревиатура от input/output control ) — это системный вызов для специфичных для устройства операций ввода/вывода и других операций, которые не могут быть выражены с помощью обычной семантики файла. Он принимает параметр, определяющий код запроса; эффект вызова полностью зависит от кода запроса. Коды запросов часто зависят от устройства. Например, драйвер устройства CD-ROM , который может дать указание физическому устройству извлечь диск, обеспечит ioctl
запросите код для этого. Коды запроса, независимые от устройства, иногда используются для предоставления пользовательскому пространству доступа к функциям ядра, которые используются только основным системным программным обеспечением или все еще находятся в стадии разработки.
The ioctl
вызов впервые появился в версии 7 Unix системный под этим именем. Он поддерживается большинством Unix и Unix-подобных систем, включая Linux и macOS , хотя доступные коды запросов различаются от системы к системе. Microsoft Windows предоставляет аналогичную функцию под названием « DeviceIoControl
", в своем Win32 API .
Фон
[ редактировать ]Обычные операционные системы можно разделить на два уровня: пользовательское пространство и ядро . Код приложения, такой как текстовый редактор, находится в пользовательском пространстве, а базовые возможности операционной системы, такие как сетевой стек , находятся в ядре. Код ядра обрабатывает конфиденциальные ресурсы и реализует барьеры безопасности и надежности между приложениями; по этой причине операционная система не позволяет приложениям пользовательского режима напрямую обращаться к ресурсам ядра.
Приложения пользовательского пространства обычно отправляют запросы к ядру посредством системных вызовов , код которых находится на уровне ядра. Системный вызов обычно принимает форму «вектора системного вызова», в котором желаемый системный вызов обозначается порядковым номером. Например, exit()
может быть системный вызов номер 1, и write()
номер 4. Вектор системного вызова затем используется для поиска нужной функции ядра для запроса. Таким образом, традиционные операционные системы обычно предоставляют несколько сотен системных вызовов пользовательскому пространству.
Хотя это и целесообразно для доступа к стандартным возможностям ядра, системные вызовы иногда не подходят для доступа к нестандартным периферийным устройствам. По необходимости большинство аппаратных периферийных устройств (также известных как устройства) напрямую адресуются только внутри ядра. Но пользовательскому коду может потребоваться напрямую взаимодействовать с устройствами; например, администратор может настроить тип носителя на интерфейсе Ethernet . Современные операционные системы поддерживают разнообразные устройства, многие из которых предлагают большой набор возможностей. Некоторые из этих возможностей могут быть не предусмотрены разработчиком ядра, и, как следствие, ядру сложно обеспечить системные вызовы для использования устройств.
Чтобы решить эту проблему, ядро спроектировано расширяемым и может принимать дополнительный модуль, называемый драйвером устройства , который работает в пространстве ядра и может напрямую обращаться к устройству. Ан ioctl
Интерфейс — это одиночный системный вызов, с помощью которого пользовательское пространство может взаимодействовать с драйверами устройств. Запросы к драйверу устройства ориентированы на это. ioctl
системный вызов, обычно с помощью дескриптора устройства и номера запроса. Таким образом, базовое ядро может позволить пользовательскому пространству получить доступ к драйверу устройства, ничего не зная о возможностях, поддерживаемых устройством, и без необходимости в неуправляемо большом наборе системных вызовов.
Использование
[ редактировать ]Конфигурация аппаратного устройства
[ редактировать ]Обычное использование ioctl
предназначен для управления аппаратными устройствами.
Например, в Win32 системах ioctl
вызовы могут взаимодействовать с USB- устройствами или получать информацию о геометрии подключенных устройств хранения данных.
В OpenBSD и NetBSD ioctl
используется bio(4)
драйвер псевдоустройства и bioctl
утилита для реализации управления томами RAID в едином независимом от поставщика интерфейсе, аналогичном ifconfig
. [1] [2]
В NetBSD ioctl
также используется sysmon
рамки. [3]
Терминалы
[ редактировать ]Одно использование ioctl
в коде, доступном приложениям конечного пользователя, есть терминальный ввод-вывод.
Операционные системы Unix традиционно широко использовали интерфейсы командной строки , первоначально с аппаратными текстовыми терминалами, такими как VT100, подключенными к последовательным портам , а затем с эмуляторами терминалов и удаленного входа серверами с использованием псевдотерминалов . Устройства последовательного порта и псевдотерминалы управляются и настраиваются с помощью ioctl
звонки. Например, размер дисплея задается с помощью TIOCSWINSZ
вызов. Функция ioctl TIOCSTI (управление вводом-выводом терминала, имитация ввода терминала) может помещать символ в поток устройства. [4]
Расширения ядра
[ редактировать ]Когда приложениям необходимо расширить ядро, например, для ускорения сетевой обработки, ioctl
вызовы предоставляют удобный способ связать код пользовательского пространства с расширениями ядра. Расширения ядра могут предоставлять место в файловой системе, которое можно открыть по имени, через которое произвольное количество ioctl
вызовы могут быть отправлены, что позволяет программировать расширение без добавления системных вызовов в операционную систему.
альтернатива sysctl
[ редактировать ]По словам разработчика OpenBSD , ioctl
и sysctl
— это два системных вызова для расширения ядра, с sysctl
возможно, это более простой из двух. [5]
В NetBSD sysmon_envsys
платформа для мониторинга оборудования использует ioctl
через proplib
; тогда как OpenBSD и DragonFly BSD вместо этого используют sysctl
для их соответствующего hw.sensors
рамки. Оригинальная редакция envsys
в NetBSD было реализовано с помощью ioctl
до proplib
был доступен и содержал сообщение о том, что фреймворк является экспериментальным и его следует заменить на sysctl(8)
интерфейс, если его разработать, [6] [7] что потенциально объясняет выбор sysctl
в OpenBSD с последующим введением hw.sensors
в 2003 году. Однако, когда envsys
структура была переработана в 2007 году примерно proplib
, системный вызов остался прежним ioctl
, и сообщение было удалено. [8]
Реализации
[ редактировать ]Юникс
[ редактировать ]The ioctl
системный вызов впервые появился в версии 7 Unix в качестве замены stty
[9] и gtty
системные вызовы с дополнительным аргументом кода запроса. Ан ioctl
вызов принимает в качестве параметров :
- дескриптор открытого файла
- номер кода запроса
- нетипизированный указатель на данные (либо идущий к драйверу, либо возвращающийся от драйвера, либо и то, и другое).
Ядро обычно отправляет ioctl
вызовите непосредственно драйвер устройства, который может интерпретировать номер запроса и данные любым необходимым способом. Авторы каждого документа драйвера запрашивают номера для этого конкретного драйвера и предоставляют их как константы в заголовочном файле .
Номера запросов обычно сочетают в себе код, идентифицирующий устройство или класс устройств, для которых предназначен запрос, и номер, указывающий конкретный запрос; код, идентифицирующий устройство или класс устройств, обычно представляет собой один символ ASCII. Некоторые системы Unix, включая 4.2BSD и более поздние выпуски BSD , операционные системы, производные от этих выпусков, и Linux , имеют соглашения, которые также кодируют в номере запроса размер данных, которые должны быть переданы в/из драйвера устройства, и направление передача данных. Независимо от того, соблюдаются ли такие соглашения, ядро и драйвер совместно выдают единый код ошибки (обозначаемый символической константой ENOTTY
) приложению, которое отправляет запрос драйверу, который его не распознает.
Мнемоника ENOTTY
(традиционно ассоциируется с текстовым сообщением « Не пишущая машинка ») происходит от самых ранних систем, которые включали в себя ioctl
звонок, где только телетайп ( tty
) устройство вызвало эту ошибку. Хотя символическая мнемоника фиксирована требованиями совместимости, некоторые современные системы более полезно отображают более общее сообщение, такое как « Неправильная операция управления устройством » (или его локализация ).
TCSETS
является примером ioctl
вызов последовательного порта . Обычные вызовы чтения и записи на последовательном порту принимают и отправляют байты данных. Ан ioctl(fd,TCSETS,data)
вызов, отдельный от обычного ввода-вывода, управляет различными параметрами драйвера, такими как обработка специальных символов или выходные сигналы порта (например, сигнал DTR ).
Win32
[ редактировать ]Win32 DeviceIoControl
принимает в качестве параметров:
- дескриптор открытого объекта (эквивалент дескриптора файла в Win32)
- номер кода запроса («контрольный код»)
- буфер для входных параметров
- длина входного буфера
- буфер для вывода результатов
- длина выходного буфера
- а
OVERLAPPED
структуру, если перекрывающийся ввод-вывод . используется
Код управления устройством Win32 учитывает режим выполняемой операции.
Существует 4 определенных режима работы, влияющих на безопасность драйвера устройства:
METHOD_IN_DIRECT
: адрес буфера проверяется на возможность чтения вызывающей стороной пользовательского режима.METHOD_OUT_DIRECT
: адрес буфера проверяется на возможность записи вызывающей стороной пользовательского режима.METHOD_NEITHER
: Виртуальные адреса пользовательского режима передаются драйверу без сопоставления или проверки.METHOD_BUFFERED
: общие буферы, управляемые диспетчером ввода-вывода, используются для перемещения данных в пользовательский режим и из него.
Альтернативы
[ редактировать ]Другие интерфейсы векторных вызовов
[ редактировать ]Устройства и расширения ядра могут быть связаны с пользовательским пространством с помощью дополнительных новых системных вызовов, хотя этот подход применяется редко, поскольку разработчики операционных систем стараются сохранить интерфейс системных вызовов целенаправленным и эффективным.
В операционных системах Unix популярны два других интерфейса векторных вызовов: fcntl
(«управление файлами») системный вызов настраивает открытые файлы и используется в таких ситуациях, как включение неблокирующего ввода-вывода ; и setsockopt
(«установить параметр сокета»), системный вызов настраивает открытые сетевые сокеты — средство, используемое для настройки ipfw
пакетный межсетевой экран в системах BSD Unix.
Отображение памяти
[ редактировать ]- Юникс
- Интерфейсы устройств и возможности ввода/вывода иногда предоставляются с использованием файлов, отображаемых в памяти . Приложения, взаимодействующие с устройствами, открывают в файловой системе место, соответствующее устройству, как это было бы для обычного устройства.
ioctl
вызов, но затем используют системные вызовы отображения памяти, чтобы связать часть их адресного пространства с адресным пространством ядра. Этот интерфейс — гораздо более эффективный способ обеспечить массовую передачу данных между устройством и приложением пользовательского пространства; индивидуальныйioctl
или системные вызовы чтения/записи вызывают накладные расходы из-за повторяющихся переходов из пользовательского пространства в ядро, где доступ к отображенному в памяти диапазону адресов не вызывает таких накладных расходов. - Win32
- Можно использовать буферизованные методы ввода-вывода или именованные объекты сопоставления файлов; однако для простых драйверов устройств стандарт
DeviceIoControl METHOD_
доступа достаточно.
Нетлинк
[ редактировать ]Netlink (IPC), похожий на сокет — это механизм межпроцессного взаимодействия , разработанный как более гибкий преемник ioctl
.
Подразумеваемое
[ редактировать ]Сложность
[ редактировать ]ioctl
вызовы минимизируют сложность интерфейса системных вызовов ядра. Однако, предоставляя разработчикам место для «прятания» фрагментов интерфейсов программирования ядра, ioctl
вызовы усложняют общий API взаимодействия пользователя с ядром. Ядро, предоставляющее несколько сотен системных вызовов, может обеспечить несколько тысяч вызовов ioctl.
Хотя интерфейс для ioctl
вызовы несколько отличаются от обычных системных вызовов, на практике разница между ними невелика. ioctl
вызов и системный вызов; а ioctl
call — это просто системный вызов с другим механизмом диспетчеризации. Таким образом, многие аргументы против расширения интерфейса системных вызовов ядра могут быть применены к ioctl
интерфейсы.
Разработчикам приложений системные вызовы кажутся ничем не отличающимися от подпрограмм приложения; это просто вызовы функций, которые принимают аргументы и возвращают значения. Библиотеки времени выполнения ОС маскируют сложность вызова системных вызовов. К сожалению, библиотеки времени выполнения не позволяют ioctl
звонки прозрачны. Простые операции, такие как определение IP-адресов машины, часто требуют запутанной путаницы. ioctl
вызовы, каждый из которых требует магических чисел и структур аргументов. [ нужна ссылка ]
Libpcap и libdnet — два примера сторонних библиотек-оболочек Unix, предназначенных для маскировки сложности ioctl
интерфейсы для захвата пакетов и ввода-вывода пакетов соответственно.
Безопасность
[ редактировать ]Интерфейсы пользователя и ядра основных операционных систем перед выпуском часто тщательно проверяются на предмет ошибок кода и уязвимостей безопасности. Эти проверки обычно сосредоточены на хорошо документированных интерфейсах системных вызовов; например, аудиторы могут гарантировать, что конфиденциальные вызовы безопасности, такие как изменение идентификаторов пользователей, доступны только администраторам.
ioctl
интерфейсы более сложны, более разнообразны, и поэтому их труднее проверять, чем системные вызовы. Кроме того, поскольку ioctl
вызовы могут предоставляться сторонними разработчиками, часто после выпуска основной операционной системы, ioctl
реализации вызовов могут подвергаться меньшему контролю и, следовательно, содержать больше уязвимостей. Наконец, многие ioctl
вызовы, особенно для сторонних драйверов устройств, недокументированы.
Поскольку обработчик для ioctl
вызов находится непосредственно в режиме ядра, ввод из пользовательского пространства должен тщательно проверяться. Уязвимости в драйверах устройств могут быть использованы локальными пользователями путем передачи недействительных буферов в ioctl
звонки.
Операционные системы Win32 и Unix могут защитить имя устройства в пользовательском пространстве от доступа приложений с помощью специальных элементов управления доступом, примененных к устройству. Проблемы безопасности могут возникнуть, когда разработчики драйверов устройств не применяют соответствующие средства управления доступом к доступному объекту пользовательского пространства.
Некоторые современные операционные системы защищают ядро от враждебного кода пользовательского пространства (например, приложений, зараженных эксплойтами переполнения буфера ) с помощью оболочек системных вызовов . Обертки системных вызовов реализуют управление доступом на основе ролей , определяя, какие системные вызовы могут быть вызваны какими приложениями; обертки могут, например, использоваться для «отмены» права почтовой программы создавать другие программы. ioctl
Интерфейсы усложняют оболочки системных вызовов, поскольку их большое количество, каждый из которых принимает разные аргументы, некоторые из которых могут потребоваться обычным программам.
Дальнейшее чтение
[ редактировать ]- В. Ричард Стивенс , Расширенное программирование в среде UNIX (Аддисон-Уэсли, 1992, ISBN 0-201-56317-7 ), раздел 3.14.
- Общие операции управления вводом-выводом в онлайн-руководстве по библиотеке GNU C.
- Unix версии 7. программиста Руководство –
- Linux программиста Руководство – Системные вызовы –
- FreeBSD по системным вызовам Руководство –
- OpenBSD по системным вызовам Руководство –
- Solaris 11.4 по системным вызовам Справочное руководство –
- «Документация DeviceIoControl в сети разработчиков Microsoft
Ссылки
[ редактировать ]- ^ Никлас Халлквист (2002 г.); Марко Пиребум (2006). «bio(4) — блок псевдо-устройства туннеля ввода-вывода ioctl» . Перекрестная ссылка BSD . OpenBSD .
{{cite web}}
: CS1 maint: числовые имена: список авторов ( ссылка )- «bio — блокировать псевдо-устройство туннеля ввода-вывода ioctl». Сервер страниц руководства OpenBSD .
- ^ Марко Пиребум (2005). «bioctl(8) — интерфейс управления RAID» . Перекрестная ссылка BSD . OpenBSD .
- «bioctl — интерфейс управления RAID». Сервер страниц руководства OpenBSD .
- ^ «sysmon(4) — интерфейс мониторинга системы и управления питанием» . НетБСД .
Интерфейс ioctl(2), доступный через /dev/sysmon.
- ^ Кристиансен, Том ; Торкингтон, Натан (1998). «12: Пакеты, библиотеки и модули». Поваренная книга Perl: решения и примеры для программистов Perl (2-е изд.). Севастополь, Калифорния: O'Reilly Media, Inc. (опубликовано в 2003 г.). п. 482. ИСБН 9780596554965 . Проверено 15 ноября 2016 г.
[...] TIOCSTI [...] означает «управление терминалом ввода-вывода, имитировать вход терминала». В системах, которые реализуют эту функцию, она будет помещать один символ в поток вашего устройства, чтобы в следующий раз, когда какой-либо процесс будет читать с этого устройства, он получил символ, который вы туда поместили.
- ^ Федерико Бьянкуцци (28 октября 2004 г.). «OpenBSD 3.6 Live» . ONLamp . О'Рейли Медиа . Архивировано из оригинала 29 октября 2004 г. Проверено 20 марта 2019 г.
Есть два системных вызова, которые можно использовать для расширения функциональности ядра (без добавления еще одного системного вызова): ioctl(2) и sysctl(3). Последнее было выбрано потому, что реализовать новую функцию было очень просто.
- ^ Тим Райтнур; Билл Сквайер (19 декабря 2007 г.). «envsys — API экологических систем» . НетБСД 4.0.
Этот API является экспериментальным и может быть признан устаревшим в любой момент... Весь этот API следует заменить интерфейсом sysctl(8) или механизмом событий ядра, если таковой будет разработан.
- ^ Константин Александрович Муренин (17 апреля 2007 г.). «3.5. sysmon NetBSD (4)». Универсальное взаимодействие с аппаратными мониторами микропроцессорной системы . Материалы Международной конференции IEEE по сетям, зондированию и управлению 2007 г., 15–17 апреля 2007 г. Лондон, Великобритания: IEEE . стр. 901–906. дои : 10.1109/ICNSC.2007.372901 . ISBN 978-1-4244-1076-7 . IEEE ICNSC 2007, стр. 901–906.
- ^ Константин Александрович Муренин (21 мая 2010 г.). «6.1. Временная шкала Framework; 7.1. NetBSD envsys/sysmon». Аппаратные датчики OpenBSD — мониторинг окружающей среды и управление вентиляторами ( диссертация на степень магистра математики ). Университет Ватерлоо : UWSpace. hdl : 10012/5234 . Идентификатор документа: ab71498b6b1a60ff817b29d56997a418.
- ^ Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Лаборатории Белла. 139. Архивировано из оригинала (PDF) 30 июля 2023 г.