Доступ к устройствам и набор I/O
В OS X пространство ядра является защищенным разделом памяти, в котором находится ядро, в то время как пространство пользователя является памятью вне раздела ядра. Большинство драйверов устройств находится в пространстве ядра, обычно потому что они берут основные прерывания (который требует, чтобы они жили в ядре), или потому что их основной клиент находится в ядре (таком как драйвер устройства для платы Ethernet, находящейся в ядре, потому что сетевые стеки находятся там).
Поскольку только кодируют выполнение в ядре, может непосредственно получить доступ к устройствам, OS X обеспечивает два механизма, позволяющие Вашему приложению или другому коду пространства пользователя использовать резидентные ядром драйверы и другие службы ядра. Эти механизмы являются интерфейсами устройства Набора I/O и поддержкой POSIX, с помощью файлов устройств.
Эта глава суммирует фундаментальные понятия Набора I/O и называет и описывает некоторые меры, которые Набор I/O принимает для поддержки устройств, присоединенных к компьютеру OS X. Затем это представляет интерфейсы устройства и файлы устройств, описывая, как они работают и где они вписываются в многоуровневую, архитектуру среды выполнения Набора I/O.
Сводка Набора I/O
Как объектно-ориентированная платформа для разработки драйвера устройства для OS X, Набор I/O определяет объекты, представляющие различные аппаратные и программные объекты, формирующие соединения I/O в рабочей системе OS X. Используя эти объекты, Набор I/O моделирует многоуровневое, связи с потребителями провайдера между устройствами, драйверами и семействами драйвера.
Набор I/O также предоставляет услуги, доступные через процедурный интерфейс, для получения информации об устройстве и доступа к устройствам от кода неядра. При помощи этого интерфейса можно получить поддержку оборудования потребности приложения без принятия сложности записи резидентного ядром кода.
Этот раздел сначала определяет условия Набора I/O, описывающие объекты, которые Вы находите в рабочей системе OS X и некоторые процессы, действующие на них. Затем это суммирует процесс обнаружения устройств и как использование интерфейсов устройства влияет на многоуровневую архитектуру рабочей системы. Для большего количества всестороннего освещения Набора I/O см. Основные принципы IOKit.
Определения Набора I/O
Набор I/O определяет объекты, представляющие оба устройства и программное обеспечение, поддерживающее их. Для работы с интерфейсами устройства или файлами устройств необходимо быть знакомы с объектно-ориентированным представлением Набора I/O устройств и программного обеспечения, составляющих рабочую систему OS X. Следующий список описывает элементы Набора I/O, процессы и структуры данных, с которыми Вы встретитесь в остальной части этого документа.
Семья (или семейство устройства) являются набором абстракций программного обеспечения, которые характерны для всех устройств определенной категории. Семьи обеспечивают функциональность, и службы к драйверам (определил затем). Набор I/O определяет семьи для протоколов шины (таких как USB и FireWire), устройства хранения, устройства интерфейса пользователя и многие другие. Для полного списка семей и какие типы основанного на приложении доступа они поддерживают, посмотрите Поддержку Доступа к устройствам семьи Набора I/O.
Драйвер является объектом Набора I/O, управляющим определенной частью аппаратных средств. Когда Набор I/O загружает драйвер, он, возможно, должен загрузить одну или более семей, также. Драйверы записаны как расширения ядра (или KEXTs) и обычно устанавливаются в каталоге
/System/Library/Extensions
.Многие из водительские характеристики найдены в его списке свойств, текстовом файле в XML (Расширяемый язык разметки) формат, описывающий содержание, настройки и требования драйвера. Драйвер обычно хранит свой список свойств (или
Info.plist
файл) вContents
каталог, где можно просмотреть его с помощью Редактора Списка свойств.Кусок является объектом Набора I/O, представляющим обнаруженный, управляемый объект, такой как устройство или логическая служба. Кусок может представлять шину, диск, графический адаптер или любое число подобных объектов. Когда это поддерживает определенную часть аппаратных средств, кусок может также быть драйвером.
Кусок поддерживает динамическую конфигурацию путем обеспечения матч-пойнта соединения между двумя драйверами (и, расширением, между двумя семьями). Кусок может также предоставить услуги для кодирования выполнения в пространстве пользователя через интерфейс устройства (определенный ниже).
Служба является объектом Набора I/O, на основе подкласса IOService, обеспечивающего определенные возможности для других объектов Набора I/O. Весь драйвер и классы куска наследовались от класса IOService. В многоуровневой архитектуре Набора I/O каждый уровень является клиентом уровня ниже его и провайдера служб к уровню выше его. Семья, кусок или драйвер могут быть поставщиком услуг к другим объектам Набора I/O.
Интерфейс устройства является библиотекой пространства пользователя или плагином, обеспечивающим интерфейс, который приложение может использовать, чтобы связаться с или управлять устройством. Интерфейс устройства связывается с его дубликатом в ядре, названный пользовательским клиентом (определил затем), для передачи команд из приложения или процесса пространства пользователя к в объекте ядра, представляющему устройство. Семья, обеспечивающая интерфейс устройства также, предоставляет пользовательскому клиенту для обработки связи стороны ядра с устройством. Для получения информации о котором семьи I/O Kit обеспечивают клиентский механизм интерфейсного пользователя устройства, видят Поддержку Доступа к устройствам семьи Набора I/O.
Пользовательский клиент является в объекте ядра, наследовавшимся от IOService и обеспечивающим соединение между драйвером устройства в ядре или куском устройства и приложением или процессом в пространстве пользователя. Некоторая документация использует термин “пользовательский клиент” для обращения к комбинации интерфейса устройства пространства пользователя и пользовательского объекта клиента в ядре, но для этого обсуждения, “пользовательский клиент” обращается к один в объекте ядра.
Реестр I/O является базой динамических данных, описывающей набор” живых” объектов, каждый из которых представляет объект Набора I/O (такой как драйвер, семья или кусок). Можно думать о Реестре I/O как о дереве с куском, представляющим основную логическую плату компьютера в корне, и различные драйверы устройств и куски как листы. В ответ на дополнение или демонтаж аппаратных средств или других изменений в системе, Реестр I/O автоматически обновляет для отражения текущей аппаратной конфигурации. (Для всестороннего взгляда на эту структуру см. Реестр I/O в Основных принципах IOKit.)
Версия разработчика OS X включает Проводник Реестра I/O (расположенный в
/Developer/Applications
), приложение, позволяющее Вам исследовать Реестр I/O своей в настоящее время рабочей системы. Существует также вызванный инструмент командной строкиioreg
то, что можно работать в Окне терминала для отображения текущей Информации о реестре I/O (Терминальное приложение расположено в/Applications/Utilities
). Для получения дополнительной информации о том, как использоватьioreg
, ввестиman ioreg
в Окне терминала.Индивидуальность драйвера является словарем пар ключ/значение, указывающих значения свойства устройства, такие как тип семьи, имя поставщика или название продукта. Драйвер подходит для любого устройства, свойства которого соответствуют одному из водительских лиц. В
Info.plist
файл, драйвер хранит свои лица как значенияIOKitPersonalities
ключ.Драйвер, соответствующий, является процессом, который Набор I/O выполняет во время начальной загрузки (и каждый раз, когда изменения настроек оборудования системы) для нахождения драйверов устройств в ядре для всех устройств в настоящее время присоединяемыми к системе. Когда это находит индивидуальность драйвера, наиболее подходящую для определенного устройства, Набор I/O инстанцирует той индивидуальности, помещает копию ее словаря индивидуальности в Реестре I/O, и (в большинстве случаев) запускает драйвер.
Соответствующий словарь является словарем пар ключ/значение, описывающих свойства устройства или другой службы. Вы создаете соответствующий словарь для указания типов устройств, к которым должно получить доступ приложение. Набор I/O обеспечивает несколько общих ключей, которые можно использовать в соответствии словаря, и много семейств устройства определяют определенные ключи и соответствие протоколов. Во время устройства, соответствующего (описал затем), значения в соответствующем словаре сравнены со свойствами куска в Реестре I/O.
Устройство, соответствующее, является процессом поиска Реестра I/O для объектов, представляющих определенное устройство или тип устройства в существующей системе. Например, приложение или другой код, работающий в OS X, могут инициировать поиск всех устройств хранения USB. В соответствии устройства Набор I/O сравнивает ключи и значения в соответствующем словаре, приложение предоставляет устройство свойства куска, сохраненные в Реестре I/O.
Файл устройств является специальным файлом, который Набор I/O создает в
/dev
папка для каждого последовательного устройства и устройства хранения это обнаруживает. Если Ваше приложение должно получить доступ к такому устройству, Вы используете функции Набора I/O, чтобы получить путь к устройству и использовать POSIX API для передачи с ним.
Платформа Набора I/O (сохраненный на диске как IOKit.framework
в /System/Library/Frameworks
) содержит широкий диапазон APIs, позволяющего Ваше рвение с устройствами. В дополнение ко многим папкам, содержащим интерфейсные устройством библиотеки и другое пространство пользователя APIs для семей I/O Kit, таких как FireWire и Хранение, платформа Набора I/O содержит несколько файлов, определяющих общий Набор I/O APIs. Эти файлы, такой как IOCFPlugIn.h
(представленный во внутренней части интерфейсный устройством механизм) и IOKitLib.h
(покрытый IOKitLib API), обеспечьте основу для коммуникации пространства пользователя ядра. Рисунок 2-1 показывает расположение Набора I/O APIs, поскольку они появляются на рабочем столе.
Для использования любого Набора I/O APIs приложение должно соединиться с IOKit.framework
.
Здание Штабеля драйвера Набора I/O
Во время начальной загрузки и каждый раз, когда изменения настроек оборудования системы, I/O Кит обнаруживает новые устройства и инстанцирует и загружает кусок, и драйвер возражает для поддержки их. Куски и драйверы формируют штабель объектов, моделирующих динамические отношения клиентского провайдера среди различного I/O объекты Кита, представляющие аппаратные и программные компоненты в соединении I/O. Как пример, считайте объекты I/O, которого инстанцирует Кит, когда он обнаруживает устройство FireWire (показанный на рисунке 2-2).
В этом примере семья IOFireWire и Набор I/O берут следующие шаги:
Набор I/O инстанцирует объекта IOFireWireController для каждого аппаратного интерфейса FireWire, такого как FireWire OHCI (Интерфейс контроллера Открытого узла), в системе OS X.
Семья IOFireWire запрашивает каждое устройство на шине и публикует объект IOFireWireDevice для каждого устройства, отвечающего его информацией о шине.
В свою очередь объект IOFireWireDevice запрашивает устройство и публикует объект IOFireWireUnit для каждого каталога модуля, который это находит на устройстве.
Несмотря на то, что это не показано на рисунке 2-2, драйверах соответствий Набора I/O к определенным типам модуля, таким как SBP-2 или AV/C, тогда публикующие куски, представляющие логические единицы.
Можно также думать о штабеле драйвера как об ответвлении в дереве Реестра I/O. Можно просмотреть объекты в любом ответвлении (штабель драйвера) с Проводником Реестра I/O. Например, рисунок 2-3 показывает представление I/O Registry Explorer части штабеля драйвера, показанного на рисунке 2-2, начинаясь с объекта IOFireWireDevice. Обратите внимание на то, что рисунок 2-3 также показывает объекту IOFireWireAVCUnit представление логического модуля AV/C.
Заметьте информацию об индивидуальности драйвера (или, для куска, информации о таблице свойства), который Проводник Реестра I/O выводит на экран для в настоящее время выбираемого элемента. Эта информация может помочь, Вы выбрать пары ключ/значение для использования для драйвера, соответствующего (для получения дополнительной информации о соответствующем драйвер процессе, посмотрите Нахождение и Доступ к Устройствам). Например, Вы могли бы принять решение искать устройства с определенным идентификатором поставщика или GUID (глобально уникальный идентификатор), оба из которых являются свойствами модуля FireWire, как показано на рисунке 2-3.
При использовании интерфейса устройства для передачи с устройством, пользовательский объект клиента присоединяется к штабелю драйвера. Семья, обеспечивающая интерфейс устройства также, обеспечивает пользовательский объект клиента, передающий команды приложения с интерфейса устройства на устройство. Когда Ваши запросы приложения интерфейс устройства для определенного устройства, семейство устройства инстанцирует надлежащего пользовательского объекта клиента, обычно присоединяя его в Реестре I/O как клиент куска устройства.
Пересматривая пример устройства FireWire, показанного на рисунке 2-2, сборе IOFireWireDeviceInterface, что семья IOFireWire обеспечивает результаты в штабеле, показанном на рисунке 2-4.
Когда I/O, Кит обнаруживает последовательное устройство или устройство хранения, это создает штабель драйверов и кусков, подобных показанным на рисунке 2-2 для устройства FireWire. Кроме того, однако, I/O Кит автоматически создает файл устройств в /dev
каталог, даже если нет никакого текущего запроса на доступ пространства пользователя к устройству. Рисунок 2-5 показывает штабель драйвера для последовательного устройства.
Как с объектами устройства FireWire, показанными на рисунке 2-3, можно использовать приложение Проводника Реестра I/O для просмотра объектов, поддерживающих последовательное устройство, поскольку рисунок 2-6 показывает.
Интерфейсы устройства и файлы устройств
Этот раздел бросает более внимательный взгляд на эти два основных шлюза к доступу к устройствам пространства пользователя, интерфейсам устройства и файлам устройств. Информация в этом разделе обеспечивает концептуальный обзор этих механизмов и не составляет пошаговое руководство для использования их. Если Вы больше интересуетесь обнаружением, как использовать интерфейсы устройства или файлы устройств в Вашем приложении, можно перейти непосредственно к Нахождению и Доступу к Устройствам.
Этот раздел завершает кратким описанием того, как Набор I/O использует порты Маха, чтобы позволить процессам пространства пользователя связываться с ядром.
В интерфейсном устройством механизме
Доступ к аппаратным средствам в OS X с интерфейсом устройства подобен в понятии использованию Диспетчера устройств в предыдущих версиях Mac OS. Вместо вызывающего устройства менеджер функционирует такой как OpenDriver
, CloseDriver
, и Control
, однако, Вы вызываете функции от Набора I/O, чтобы получить интерфейс устройства, затем вызвать функции, которые интерфейс устройства определяет, такой как open
, close
, и getInquiryData
.
Интерфейс устройства является сменным интерфейсом, соответствующим Базовой модели плагина Основы (описанный в Базовой документации разработчика Основы, доступной в Базовой Ссылочной Библиотеке Основы). Также, это совместимо с основами COM Microsoft (Объектная модель компонентов) архитектура. На практике, единственные элементы, интерфейс устройства доли с COM является расположением самого интерфейса (который соответствует инструкциям COM), и его наследование от COM-совместимого IUnknown
интерфейс.
После Базовой модели плагина Основы взаимодействует через интерфейс семья I/O Kit, обеспечивающая устройство, сначала определяет тип, представляющий набор интерфейсов, которые это поддерживает. Затем это определяет каждый интерфейс, объявляя функции интерфейсные реализации. Тип и интерфейсы, каждый получает UUID (универсальный уникальный идентификатор или ID), 128-разрядное значение, уникально и постоянно идентифицирующее его. Семья делает их UUIDs доступный как предопределенное имя Ваше использование приложения, когда она запрашивает интерфейс устройства. Например, семья IOFireWire определяет свою версию 5 интерфейс UUID устройства FireWire как kIOFireWireDeviceInterfaceID_v5
, который намного проще использовать, чем сама строка UUID, 127A12F6-C69F-11D6-9D11-0003938BEB0A
.
Прежде чем приложение может получить определенный, определенный семьей интерфейс устройства, это сначала получает экземпляр промежуточного плагина типа IOCFPlugInInterface. Определенный в IOCFPlugIn.h
(в платформе Набора I/O), структура IOCFPlugInInterface начинается IUNKNOWN_C_GUTS
макрос, определенный в CFPlugInCOM.h
(в Базовой платформе Основы). Этот макрос расширяется в определение структуры COM IUnknown
интерфейс. Это означает, что экземпляр IOCFPlugInInterface начинается IUnknown
функции интерфейса, требуемые для всех интерфейсов на основе Базовой модели плагина Основы, показанной на рисунке 2-7.
AddRef
и Release
функции воздействуют на подсчеты ссылок объекта IOCFPlugInInterface и QueryInterface
функция создает новые экземпляры переданного - в интерфейсном типе, такие как устройство взаимодействуют через интерфейс, семья I/O Kit определяет.
IOCFPlugIn.h
файл также определяет функцию IOCreatePlugInInterfaceForService
, который создает новый объект IOCFPlugInInterface, и IODestroyPlugInInterface
, который уничтожает указанный объект IOCFPlugInInterface.
После того, как Ваше приложение получает объект IOCFPlugInInterface, оно тогда вызывает QueryInterface
функция, предоставляя его (среди других параметров) определенное семьей имя UUID определенного устройства соединяет интерфейсом с потребностями приложения. QueryInterface
функционируйте возвращает экземпляр требуемого интерфейса устройства, и приложение тогда имеет доступ ко всем функциям, которые обеспечивает интерфейс устройства. Например, интерфейс устройства семьи USB для USB-устройств обеспечивает функции, показанные на рисунке 2-8.
Как показано на рисунке 2-8, определенный семьей интерфейс устройства также начинается AddRef
, Release
, и QueryInterface
функции. Это вызвано тем, что интерфейс устройства семьи, как IOCFPlugInInterface, выполняет требование COM, чтобы все интерфейсы наследовались от IUnknown
интерфейс. Ваше приложение никогда не должно будет, вероятно, использовать эти три функции из интерфейса устройства, однако, потому что наиболее определенные семьей интерфейсы устройства обеспечивают свое собственное средство доступа и функции подсчета ссылок.
Приложение, получившее интерфейс устройства для устройства, может действовать как драйвер пространства пользователя для того устройства. Например, приложение может управлять сканером, соответствующим спецификациям Модели архитектуры SCSI, потому что Apple не предоставляет в драйвере ядра для такого устройства. См. документацию для семейства устройства, к которому Вы хотите получить доступ для получения дополнительной информации.
В механизме файла устройств
Дарвин, ядро OS X, реализует версию 4.4BSD, основанная на UNIX операционная система, служащая основанием для файловых систем и сетевых средств OS X. Кроме того, реализация Дарвином BSD включает большую часть POSIX API. Дарвин экспортирует программируемые интерфейсы, соответствующие POSIX API к пространству приложения, позволяющий приложениям связываться с последовательным, хранением и сетевыми устройствами через файлы устройств.
В файловой системе UNIX файл устройства ввода-вывода является специальным файлом, представляющим блочное устройство или устройство посимвольного ввода-вывода, такое как терминал, дисковод, принтер, сканер или лентопротяжное устройство. В сущности файл устройств действует как буфер или поток данных для устройства. Исторически, файлы устройств находятся в /dev
каталог и имеет стандартные имена, такой как mt0
для первого устройства магнитной ленты, tty0
для первого терминала, и т.д. Поскольку система UNIX обрабатывает файл устройств как любой другой дисковый файл, можно использовать команды UNIX с файлами устройств для выполнения операций ввода и вывода на устройствах. При отправке данных в файл устройств ядро прерывает их и перенаправляет их к устройству. Точно так же, когда процесс читает из файла устройств, ядро получает данные от устройства и передает его приложению.
Поскольку это делает с другими устройствами, когда I/O, Кит обнаруживает последовательное устройство или устройство хранения, это накапливает штабель драйвера для поддержки его. Кроме того, это инстанцирует пользовательского объекта клиента BSD, создающего узел файла устройств в /dev
каталог. Пользовательский объект клиента BSD действует как кабелепровод между клиентом, получающим доступ к устройству через файл устройств и представлением в объектах ядра устройства. Для последовательного устройства Набор I/O инстанцирует объекта IOSerialBSDClient и для устройства хранения, Набор I/O инстанцирует объекта IOMediaBSDClient.
Когда приложение должно получить доступ к последовательному устройству или устройству хранения, для которого оно уже не имеет пути файла устройств, оно может использовать функции Набора I/O для нахождения согласующего устройства в Реестре I/O. Приложение может тогда исследовать свойства объекта для получения его пути файла устройств. Свойства, которые Вы используете для создания строки пути, варьируются несколько в зависимости от того, получаете ли Вы доступ к последовательному устройству или устройству хранения; для большего количества подробных данных посмотрите Нахождение и Доступ к Устройствам.
На рисунке 2-9, отображения приложения Проводника Реестра I/O свойства IOSerialBSDClient для модема.
Из-за динамической и параллельной природы системы OS X устройство может получить различное имя файла устройств каждый раз I/O, Кит обнаруживает его. Поэтому необходимо искать Реестр I/O устройство, которым Вы интересуетесь получить текущий путь файла устройств, прежде чем Вы попытаетесь получить доступ к устройству вместо жесткого кодирования имя файла устройств, такой как /dev/cu.modem
или /dev/rdisk0
, в Вашем приложении. Когда у Вас есть корректный путь к устройству (включая имя файла устройств), Вы тогда используете любой POSIX функции, такой какopen
иclose
, связываться с устройством хранения или POSIX termios
API для традиционного доступа последовательного порта UNIX к последовательному устройству. Для последовательных устройств данные также направляются через PPP через файл устройств.
Для получения информации о стандарте POSIX посмотрите http://standards .ieee.org. Для ссылки программирования POSIX посмотрите Руководство Программиста POSIX: Запись Переносимых Программ Unix с POSIX Дональдом A. Lewine.
Если Ваше приложение должно получить доступ к сетевому соединению, оно делает настолько использующий определенный IP-адрес и стандартные функции сокета. Набор I/O накапливает штабели объектов поддерживать сетевые устройства, которые подобны штабелям драйвера для других устройств. Поскольку Ваше приложение касается доступа к соединению вместо объекта устройства, однако, нахождение, что эти объекты в Реестре I/O являются ненужными.
OS X обеспечивает сетевой APIs в Углероде и Какао, которое должно обработать большинство стандартных требований сетевых соединений для приложений. Можно также использовать сокеты BSD API для получения сетевых служб. Рекомендуемая книга сетевого программирования является Сетевым программированием Unix, Объемом 1, Второй Выпуск, W. Ричард Стивенс, Прентис-Хол PTR, 1998.
Связь с набором I/O
Использует ли Ваше приложение интерфейсы устройства или файлы устройств к устройствам доступа, оно должно связаться с Набором I/O. Набор I/O API (в платформе Набора I/O) включает функции, чтобы искать Реестр I/O определенные устройства или группы устройств, получить доступ к объектам Набора I/O, и к свойствам индивидуальности устройства доступа и драйвера, опубликованным в Реестре I/O. Когда приложение использует эти функции, оно связывается с Набором I/O через порт Маха, однонаправленный канал передачи между клиентом, запрашивающим службу и сервер (в этом случае, Набор I/O), который предоставляет услугу.
Фундаментальные службы и примитивы Дарвина основываются на расширенной версии Apple Маха 3.0. Улучшения Apple позволяют Маху предоставлять основанному на объектах APIs каналы передачи (такие как порты), полный набор IPC (межпроцессное взаимодействие) примитивы и улучшенная мобильность, среди других функций. Когда приложение или другой процесс пространства пользователя связываются с Набором I/O, это делает так при помощи RPC (вызовы удаленной процедуры) на ведущем порту Набора I/O.
В частности, Ваши запросы приложения ведущий порт Набора I/O, с помощью функции Набора I/O IOMasterPort
, прежде чем это попытается получить доступ немного в объектах ядра, такие как объекты Реестра I/O, представляющие устройства. (Также это может использовать постоянное удобство kIOMasterPortDefault
для доступа к ведущему порту Набора I/O — для получения дополнительной информации о том, как сделать это посмотрите Получение Ведущего порта Набора I/O.)
IOMasterPort
вызовы функции host_get_io_master
функция mach_host.c
, который возвращает отправить право на приложение. Это означает, что приложение имеет право использовать порт для доступа к объекту с другой стороны порта, в этом случае, объекта Набора I/O.
Не волнуйтесь, не ли Вы хорошо осведомлены о Махе. За исключением сбора ведущего порта Набора I/O и некоторых проблем подсчета ссылок (обсужденный в Объектном Подсчете ссылок и Самоанализе), основанная на Махе инфраструктура Дарвина редко представляется при использовании Набора I/O для доступа к аппаратным средствам. Если Вы интересуетесь узнаванием больше, как Дарвин использует Маха, однако, см. Руководство по программированию Ядра для хорошего введения.