ioctl - ioctl

редактировать

В вычислении, ioctl(сокращение от элемент управления вводом / выводом ) - это системный вызов для специфичных для устройства операций ввода / вывода и других операций, которые не могут быть выражены обычными системными вызовами. Требуется параметр, указывающий код запроса; эффект вызова полностью зависит от кода запроса. Коды запросов часто зависят от устройства. Например, драйвер устройства CD-ROM , который может дать команду физическому устройству извлечь диск, предоставит для этого код запроса ioctl. Коды запросов, не зависящие от устройства, иногда используются для предоставления пользовательского пространства доступа к функциям ядра, которые используются только основным системным программным обеспечением или все еще находятся в стадии разработки.

Системный вызов ioctlвпервые появился под этим именем в версии 7 из Unix. Он поддерживается большинством Unix и Unix-подобных систем, включая Linux и macOS, хотя доступные коды запросов различаются от системы к системе. Microsoft Windows предоставляет аналогичную функцию под названием «DeviceIoControl» в своем Win32 API.

Содержании

  • 1 Фон
  • 2 Использует
    • 2.1 Оборудование конфигурация устройства
    • 2.2 Терминалы
    • 2.3 Расширения ядра
      • 2.3.1 Альтернатива sysctl
  • 3 Реализации
    • 3.1 Unix
    • 3.2 Win32
  • 4 Альтернативы
    • 4.1 Другие интерфейсы векторных вызовов
    • 4.2 Отображение памяти
    • 4.3 Netlink
  • 5 Последствия
    • 5.1 Сложность
    • 5.2 Безопасность
  • 6 Дополнительная литература
  • 7 Ссылки

Предпосылки

Обычные операционные системы могут быть разделенным на два уровня: пользовательское пространство и ядро ​​. Код приложения, такой как a, находится в пользовательском пространстве, в то время как базовые возможности операционной системы, такие как сетевой стек, находятся в ядре. Код ядра обрабатывает конфиденциальные ресурсы и реализует барьеры безопасности и надежности между приложениями; по этой причине операционная система не позволяет приложениям пользовательского режима напрямую обращаться к ресурсам ядра.

Пользовательское пространство приложения обычно делают запросы к ядру с помощью системных вызовов, код которых находится на уровне ядра. Системный вызов обычно принимает форму «вектора системного вызова», в котором желаемый системный вызов обозначается порядковым номером. Например, exit ()может быть номером системного вызова 1, а write ()номером 4. Затем вектор системного вызова используется для поиска требуемой функции ядра для запроса. Таким образом, обычные операционные системы обычно предоставляют несколько сотен системных вызовов пользовательскому пространству.

Несмотря на то, что это целесообразный дизайн для доступа к стандартным средствам ядра, системные вызовы иногда не подходят для доступа к нестандартным периферийным устройствам оборудования. По необходимости, большинство аппаратных периферийных устройств (также называемых устройствами) имеют прямую адресацию только внутри ядра. Но пользовательскому коду может потребоваться прямая связь с устройствами; например, администратор может настроить тип носителя на интерфейсе Ethernet. Современные операционные системы поддерживают различные устройства, многие из которых предлагают большой набор функций. Некоторые из этих возможностей могут быть не предусмотрены разработчиком ядра, и, как следствие, ядру трудно обеспечить системные вызовы для использования устройств.

Чтобы решить эту проблему, ядро ​​спроектировано так, чтобы быть расширяемым, и может принимать дополнительный модуль, называемый драйвером устройства, который работает в пространстве ядра и может напрямую обращаться к устройству. Интерфейс ioctl- это отдельный системный вызов, с помощью которого пользовательское пространство может взаимодействовать с драйверами устройств. Запросы к драйверу устройства направляются относительно этого системного вызова ioctl, обычно с помощью дескриптора устройства и номера запроса. Таким образом, базовое ядро ​​может позволить пользовательскому пространству получить доступ к драйверу устройства, ничего не зная о средствах, поддерживаемых устройством, и без необходимости в неуправляемом большом наборе системных вызовов.

Использует

Конфигурация аппаратного устройства

Обычно ioctlиспользуется для управления аппаратными устройствами.

Например, в системах Win32 вызовы ioctlмогут обмениваться данными с устройствами USB или могут обнаруживать информацию о геометрии дисков подключенного устройства хранения данных.

В OpenBSD и NetBSD, ioctlиспользуется bio(4) драйвер псевдоустройства и утилита bioctl для реализации управления томами RAID в унифицированном независимом от производителя интерфейсе, аналогичном ifconfig .

В NetBSD, ioctlтакже используется фреймворком sysmon .

Терминалы

Один использование ioctlв коде, доступном для приложений конечного пользователя, является терминальным вводом-выводом.

Операционные системы Unix традиционно интенсивно использовали интерфейсы командной строки. Интерфейс командной строки Unix построен на псевдотерминалах (ptys), которые имитируют аппаратные текстовые терминалы, такие как VT100s. Pty управляется и настраивается, как если бы это было аппаратное устройство, с помощью вызовов ioctl. Например, размер окна объекта устанавливается с помощью вызова TIOCSWINSZ. Функция ioctl TIOCSTI (управление вводом-выводом терминала, имитация ввода-вывода) может протолкнуть символ в поток устройства.

Расширения ядра

Когда приложениям необходимо расширить ядро, например, для ускорения при сетевой обработке вызовы ioctlпредоставляют удобный способ связать код пользовательского пространства с расширениями ядра. Расширения ядра могут предоставить место в файловой системе, которое может быть открыто по имени, через которое может быть отправлено произвольное количество вызовов ioctl, что позволяет программировать расширение без добавления системных вызовов к операционной системе.

альтернатива sysctl

По словам разработчика OpenBSD, ioctlи sysctl являются двумя системные вызовы для расширения ядра, причем sysctl, возможно, является более простым из двух.

В NetBSD, sysmon_envsys framework для аппаратного мониторинга использует ioctl- proplib ; тогда как OpenBSD и DragonFly BSD вместо этого используют sysctl для своих соответствующих hw.sensors фреймворк. Исходная версия envsysв NetBSD была реализована с помощью ioctlдо того, как был доступен proplib, и содержала сообщение о том, что структура является экспериментальной и должна быть заменена интерфейс sysctl (8), если он будет разработан, что потенциально объясняет выбор sysctlв OpenBSD с его последующим введением hw.sensors в 2003 году. Однако, когда структура envsys была переработана в 2007 году около proplib, системный вызов остался как ioctl, и сообщение было удалено.

Реализации

Unix

Системный вызов ioctlвпервые появился в версии 7 Unix, как a переименован в stty . Вызов ioctlпринимает в качестве параметров :

  1. открытый файловый дескриптор
  2. номер кода запроса
  3. либо целочисленное значение, возможно, без знака (переход к драйверу) или указатель на данные (либо идущий к драйверу, либо возвращающийся из драйвера, либо оба).

ядро ​​ обычно отправляет ioctlвызовите прямо к драйверу устройства, который может интерпретировать номер запроса и данные любым необходимым способом. Авторы каждого документа драйвера запрашивают номера для этого конкретного драйвера и предоставляют их как константы в заголовочном файле.

Некоторые системы Unix, включая Linux, имеют соглашения, которые кодируют в номере запроса - размер данных, которые должны быть переданы в / из драйвера устройства, направление передачи данных и идентификатор драйвера, реализующего запрос. Независимо от того, соблюдается ли такое соглашение, ядро ​​и драйвер взаимодействуют, чтобы доставить единый код ошибки (обозначается символической константой ENOTTY) приложению, которое делает запрос к драйверу, который его не распознает..

Мнемоника ENOTTY(традиционно связанная с текстовым сообщением «Не пишущая машинка ») происходит от самых ранних систем, которые включали вызов ioctl, где только устройство телетайпа (tty) вызвало эту ошибку. Хотя символическая мнемоника фиксируется требованиями совместимости, некоторые современные системы более эффективно отображают более общее сообщение, такое как «Несоответствующая операция управления устройством» (или его локализация ).

TCSETSиллюстрирует вызов ioctlна последовательном порту. Обычные вызовы чтения и записи через последовательный порт принимают и отправляют байты данных. Вызов ioctl (fd, TCSETS, data), отдельный от такого обычного ввода-вывода, управляет различными параметрами драйвера, такими как обработка специальных символов или выходных сигналов порта (например, как сигнал DTR ).

Win32

Win32 DeviceIoControlпринимает в качестве параметров:

  1. дескриптор открытого объекта (эквивалент дескриптора файла в Win32)
  2. запрос номер кода («контрольный код»)
  3. буфер для входных параметров
  4. длина входного буфера
  5. буфер для выходных результатов
  6. длина выходной буфер
  7. структура OVERLAPPED, если используется перекрывающийся ввод-вывод.

Управляющий код устройства Win32 принимает во внимание режим работы выполняется.

Существует 4 определенных режима работы, влияющих на безопасность драйвера устройства -

  1. METHOD_IN_DIRECT: адрес буфера проверяется на возможность чтения вызывающим режимом пользовательского режима.
  2. METHOD_OUT_DIRECT: Адрес буфера проверяется на возможность записи вызывающим режимом пользовательского режима.
  3. METHOD_NEITHER: виртуальные адреса пользовательского режима передаются драйверу без сопоставления или проверки.
  4. METHOD_BUFFERED: общий доступ, управляемый диспетчером ввода-вывода буферы используются для перемещения данных в пользовательский режим и из него.

Альтернативы

Другие интерфейсы векторных вызовов

Устройства и расширения ядра могут быть связаны с пользовательским пространством с помощью дополнительных новых системные вызовы, хотя этот подход применяется редко, потому что разработчики операционных систем стараются сохранить интерфейс системных вызовов сфокусированным и эффективным.

В операционных системах Unix популярны два других интерфейса векторных вызовов: системный вызов fcntl(«управление файлами») настраивает открытые файлы и используется в таких ситуациях, как включение неблокирующий ввод / вывод ; а системный вызов setsockopt("установить параметр сокета") настраивает открытые сетевые сокеты, средство, используемое для настройки межсетевого экрана пакетов ipfw в системах BSD Unix.

Отображение памяти

Unix
Интерфейсы устройств и возможности ввода / вывода иногда предоставляются с помощью файлов с отображением памяти. Приложения, которые взаимодействуют с устройствами, открывают место в файловой системе, соответствующее устройству, как это было бы для вызова ioctl, но затем используют системные вызовы отображения памяти, чтобы связать часть своего адресного пространства с адресным пространством ядра.. Этот интерфейс - гораздо более эффективный способ обеспечить массовую передачу данных между устройством и приложением пользовательского пространства ; отдельные системные вызовы ioctlили чтение / запись вызывают накладные расходы из-за повторяющихся переходов из пользовательского пространства в ядро, когда доступ к диапазону адресов, отображаемых в памяти, не вызывает таких накладных расходов.
Win32
Могут использоваться буферизованные методы ввода-вывода или именованные объекты сопоставления файлов; однако для простых драйверов устройств достаточно стандартного доступа DeviceIoControl METHOD_.

Netlink

Netlink - это механизм, подобный сокету, для межпроцессного взаимодействия (IPC), разработанный как более гибкий преемник для вызовов ioctl.

Implications

Complexity

ioctl, минимизирует сложность интерфейса системных вызовов ядра. Однако, предоставляя разработчикам место для «спрятать» кусочки и части программных интерфейсов ядра, вызовы ioctlусложняют общий API взаимодействия пользователя с ядром. Ядро, которое предоставляет несколько сотен системных вызовов, может обеспечивать несколько тысяч вызовов ioctl.

Хотя интерфейс для вызовов ioctlнесколько отличается от обычных системных вызовов, на практике разница между вызовом ioctlи системным вызовом незначительна; вызов ioctl- это просто системный вызов с другим механизмом диспетчеризации. Поэтому многие аргументы против расширения интерфейса системного вызова ядра можно применить к интерфейсам ioctl.

Для разработчиков приложений системные вызовы не отличаются от подпрограмм приложения; это просто вызовы функций, которые принимают аргументы и возвращают значения. Библиотеки среды выполнения ОС маскируют сложность, связанную с вызовом системных вызовов. К сожалению, библиотеки времени выполнения не делают вызовы ioctlпрозрачными. Простые операции, такие как обнаружение IP-адресов для машины, часто требуют запутанных беспорядочных вызовов ioctl, каждый из которых требует магических чисел и структур аргументов.

Libpcap и являются двумя примерами сторонних библиотек-оболочек Unix, предназначенных для маскировки сложности интерфейсов ioctlдля захвата пакетов и ввода-вывода пакетов соответственно.

Безопасность

Интерфейсы пользователь-ядро в основных операционных системах перед выпуском часто подвергаются тщательному аудиту на предмет недостатков кода и уязвимостей безопасности. Эти аудиты обычно фокусируются на хорошо задокументированных интерфейсах системных вызовов; например, аудиторы могут гарантировать, что конфиденциальные вызовы безопасности, такие как изменение идентификаторов пользователей, доступны только администраторам.

ioctlинтерфейсы сложнее, разнообразнее и, следовательно, труднее контролировать, чем системные вызовы. Кроме того, поскольку вызовы ioctlмогут предоставляться сторонними разработчиками, часто после выпуска основной операционной системы реализации вызовов ioctlмогут подвергаться меньшему вниманию и, таким образом, содержать больше уязвимостей. Наконец, многие вызовы ioctl, особенно для сторонних драйверов устройств, недокументированы.

Поскольку обработчик вызова ioctlнаходится непосредственно в режиме ядра, ввод из пользовательского пространства следует тщательно проверять. Уязвимости в драйверах устройств могут быть использованы локальными пользователями путем передачи недопустимых буферов вызовам ioctl. Операционные системы

Win32 и Unix могут защитить имя устройства пользовательского пространства от доступа приложений с определенными элементами управления доступом, применяемыми к устройству. Проблемы безопасности могут возникнуть, когда разработчики драйверов устройств не применяют соответствующие средства управления доступом к доступному объекту пользовательского пространства.

Некоторые современные операционные системы защищают ядро ​​от использования вредоносного кода пользовательского пространства (например, приложений, зараженных эксплойтами переполнения буфера ). Оболочки системных вызовов реализуют ролевое управление доступом, указывая, какие системные вызовы могут быть вызваны какими приложениями; Обертки могут, например, использоваться для "отзыва" права почтовой программы на порождение других программ. Интерфейсы ioctlусложняют обертки системных вызовов, поскольку их большое количество, каждый из которых принимает разные аргументы, некоторые из которых могут потребоваться для обычных программ.

Дополнительная литература

Ссылки

Последняя правка сделана 2021-05-24 05:51:44
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте