IOKitLib API
При доступе к устройству от пространства пользователя используете ли Вы интерфейс устройства или POSIX API, Вы используете комбинацию функций Набора I/O и определенных функций семьи устройства для работы с объектами Набора I/O, представляющими устройство. IOKitLib, расположенный в платформе Набора I/O, содержит универсальные функции Набора I/O, которые Вы используете для реализации доступа задачи пространства пользователя к объектам устройства в ядре.
Эта глава рассматривает функции IOKitLib, описывая, как использовать их, чтобы получить доступ к и управлять в объектах ядра и обеспечение понимания, как IOKitLib реализует эти функции.
Некоторые функции в IOKitLib предназначаются для разработчиков интерфейсов отдельного устройства, а не для разработчиков приложений, использующих существующие интерфейсы устройства. Несмотря на то, что эта глава касается этих функций на высоком уровне, необходимо считать Аппаратные средства Создания, Доступные для Приложений в Руководстве по проектированию Драйвера устройства IOKit, если необходимо разработать собственное клиентское решение интерфейсного пользователя устройства.
Функции IOKitLib могут быть разделены на несколько категорий, на основе типа услуги, которую они предоставляют. Эта глава зеркально отражает эти группировки и разделена на следующие разделы, каждый из которых покрывает функциональную категорию:
Объектный Подсчет ссылок и Самоанализ представляют типы объектов, которые Вы используете для передачи с объектами в ядре, и описывает, как получить информацию о них и отслеживать их подсчеты ссылок.
Обнаружение устройств и Уведомление описывают функции, которые Вы используете, чтобы создать соответствие словарей, искать и согласующие устройства доступа в Реестре I/O и получить уведомления об изменении состояния устройства.
Доступ к реестру I/O описывает другие функции IOKitLib, которые можно использовать для получения доступа к объектам в Реестре I/O.
Интерфейсная устройством Разработка дает краткий обзор функций IOKitLib, которые Вы используете, когда никакая семья устройства Набора I/O или сторонний интерфейс устройства не существуют, и необходимо разработать собственный интерфейс устройства.
Объектный подсчет ссылок и самоанализ
Функции в IOKitLib связываются с использованием в объектах ядра транспортного механизма порта Маха для пересечения границы пользовательского ядра. Файл IOTypes.h
, расположенный в платформе Набора I/O, определяет объекты, которые Вы используете с функциями IOKitLib для передачи с такими объектами в ядре как Ключи реестра I/O (объекты класса IORegistryEntry) или итераторы (объекты класса IOIterator). Заметьте в Перечислении 4-1, однако, этом IOTypes.h
кажется, определяет все эти объекты таким же образом, в частности, как mach_port_t
объекты (mach_port_t
определяется в mach/port.h
в платформе Ядра).
Определения объектов перечисления 4-1 в IOTypes.h
typedef mach_port_t io_object_t; |
typedef io_object_t io_connect_t; |
typedef io_object_t io_iterator_t; |
typedef io_object_t io_registry_entry_t; |
typedef io_object_t io_service_t; |
typedef io_object_t io_enumerator_t; |
Для понимания, почему это так вспомните, что порт Маха является коммуникационным транспортным механизмом, который приложение использует для передачи с Набором I/O. Насколько ядро затронуто, каждый раз, когда Ваше приложение передает с любым использование в объекте ядра одних из типов объектов, определенных в IOTypes.h
, это использует тот же универсальный механизм (а именно, порт Маха) для пересечения границы пользовательского ядра.
С точки зрения приложения, однако, транспортный механизм неважен и что имеет значение, тип объекта с другой стороны порта. Факт, что io_iterator_t
объект, например, инкапсулирует ассоциацию порта Маха с объектом IOIterator в ядре, не так важно для приложения как факт что io_iterator_t
объект относится к в объекте ядра, знающему, как выполнить итерации по Реестру I/O.
io_object_t
объекты в пространстве пользователя не только относятся к в объектах ядра, они также отражают иерархию класса C++ в ядре. Поскольку IOService является подклассом IORegistryEntry, например, можно использовать io_service_t
объект с любой функцией IOKitLib, ожидающей io_registry_entry_t
объект, такой как IORegistryEntryGetPath
.
За редким исключением (такие как то, чтобы заставлять ведущий порт Набора I/O инициировать связь с Набором I/O и подсчетом ссылок io_object_t
сами объекты), Вы не должны интересоваться перекрестным граничным механизмом связи. Скорее необходимо фокусироваться на определенном в объекте ядра, с которым Вы работаете, удостоверяясь, что Вы используете каждый тип объекта соответственно.
Подсчет ссылок
IOKitLib содержит три функции подсчета ссылок:
Каждая из этих функций воздействует на сохранить количество базового объекта ядра (объект с другой стороны порта Маха) а не на io_object_t
возразите себе. Другими словами, если Вы хотите сохранить, выпустить или добраться, сохранить количество IORegistryEntry в ядре возражают io_registry_entry_t
объект представляет, Вы используете одну из функций подсчета ссылок IOKitLib. Например, Перечисление 4-2 показывает фрагмент кода, выпускающий объект IOIterator в ядре лежание в основе io_iterator_t
объект после того, как это использовалось для нахождения модема последовательного порта.
Перечисление 4-2 , Выпускающее базовый объект ядра io_iterator_t
объект
io_iterator_t serialPortIterator = NULL; |
char deviceFilePath[ MAXPATHLEN ]; |
kernResult = MyFindSerialPortModems(&serialPortIterator, &masterPort); |
if (kernResult == kIOReturnSuccess) { |
kernResult = MyGetPathOfFirstModem (serialPortIterator, deviceFilePath, |
sizeof(deviceFilePath)); |
//Release the iterator since we want only the first modem. |
IOObjectRelease(serialPortIterator); |
//If MyGetPathOfFirstModem found a modem, communicate with it. |
... |
} |
Как хорошую практику программирования, необходимо использовать IOObjectRelease
выпускать все io_object_t
объекты, которые Вы создаете в своем коде, когда они больше не необходимы.
Если Вы подозреваете, что просачиваетесь io_object_t
объекты, однако, IOObjectGetRetainCount
не поможет Вам, потому что эта функция сообщает Вам о базовом объекте ядра, сохраняют количество (который часто намного выше). Вместо этого потому что сохранить количество io_object_t
объект является по существу сохранить количеством отправить прав на порту Маха, Вы используете функцию Маха для получения этой информации. Перечисление 4-3 показывает, как использовать функцию Махаmach_port_get_refs
(определенный в mach/mach_port.h
в платформе Ядра) для получения сохранить количества io_object_t
объект.
Перечисление 4-3 , Получающее сохранить количество io_object_t
объект
#include <mach/mach_port.h> |
kern_return_t kr; |
unsigned int count; |
io_object_t theObject; |
kr = mach_port_get_refs ( mach_task_self(), theObject, MACH_PORT_RIGHT_SEND, |
&count ); |
printf ("Retain count for object ID %#X is %d\n", theObject, count); |
Самоанализ
IOKitLib обеспечивает три функции объектного самоанализа, управляющие на в объекте ядра переданным - в io_object_t
объект представляет (не io_object_t
сам объект):
Первая функция, IOObjectConformsTo
, просто выполняет в объекте ядра metaCast
метод и возвраты булев результат. IOObjectGetClass
вызовы функции в объекте ядра getMetaClass
метод и затем вызывает тот класс getClassName
метод для возврата имени класса как струны до. IOKitLib реализует IOObjectIsEqualTo
функционируйте как мелкое сравнение указателя этих переданных двух - в объектах, возвращая результат как булево значение.
Обнаружение устройств и уведомление
Даже при использовании немногих других функций IOKitLib в приложении доступа к устройствам Вы будете, конечно, использовать функции обнаружения устройств. Если Вы работаете с заменяемыми в горячем режиме устройствами, такими как USB или устройства FireWire, можно также использовать функции уведомления.
Следующие разделы покрывают обнаружение устройств IOKitLib и функции уведомления, описывая, как IOKitLib реализует:
Соответствие создания словаря
Поиск устройства
Установка уведомления
Итерация устройства
Создание соответствия словарей
При использовании функций IOKitLib для создания соответствующего словаря, Вы получаете ссылку на Базовый объект словаря Основы. IOKitLib использует Базовые Фундаментальные классы, такие как CFMutableDictionary и CFString, потому что они близко соответствуют набору в ядре и контейнерным классам, таким как OSDictionary и OSString (определенный в libkern/c++
в платформе Ядра).
Набор I/O автоматически переводит объект CFDictionary в свой дубликат в ядре, когда он пересекает границу пользовательского ядра, позволяя Вам создать объект в пространстве пользователя, позже использующемся в ядре. Для получения дополнительной информации об использовании Базовой Основы возражает, чтобы представлять в объектах ядра, видеть Свойства Просмотра Объектов Реестра I/O.
IOKitLib определяет следующие функции для создания соответствия словарей:
Эти функции создают непостоянный Базовый объект словаря Основы, содержащий надлежащий ключ и Ваш переданный - в значении. Таблица 4-1 показывает ключам каждое использование функций создания словаря, вместе с файлами платформы Набора I/O, в которых определяются ключи.
Имя функции | Ключевое имя | Файл ключевого определения |
---|---|---|
|
| |
|
| |
|
|
Если, например, Вы вызываете IOServiceNameMatching
с i2c-модемом параметра получающийся словарь похож на это:
{ |
IONameMatch = i2c-modem; |
} |
Все функции создания словаря возвращают ссылку на объект CFMutableDictionary. Обычно, Вы передаете словарь одной из функций поиска (обсужденный затем в Поиске Устройств), каждый из которых использует одну ссылку на него. При использовании словаря некоторым другим способом необходимо скорректировать сохранять количество соответственно, с помощью CFRetain
или CFRelease
(определенный в Базовой платформе Основы).
Поиск устройств
IOKitLib обеспечивает три функции поиска, ищущие зарегистрированные объекты в Реестре I/O, соответствующие переданный - в соответствии словаря:
IOKitLib реализует свою самую общую функцию поиска, IOServiceGetMatchingServices
, путем преобразования соответствия словаря в объект OSDictionary и вызов метода IOService getMatchingServices
. Этот метод возвращает объект IOIterator, содержащий список соответствия объектов IOService. IOServiceGetMatchingServices
тогда выпускает соответствующий словарь, в котором Вы передали и возвращаете Вам io_iterator_t
объект, представляющий объект IOIterator в ядре.
IOServiceGetMatchingService
функция является просто особым случаем IOServiceGetMatchingServices
: Это возвращает первый соответствующий объект в списке вместо итератора, обеспечивающего доступ ко всему списку.
Если Вы получаете io_iterator_t
объект от IOServiceGetMatchingServices
, необходимо выпустить его с IOObjectRelease
когда Вы закончены с ним; точно так же необходимо использовать IOObjectRelease
выпускать io_object_t
объект Вы получаете из IOServiceGetMatchingService
.
IOServiceAddMatchingNotification
функционируйте не, только ищет соответствующие объекты в Реестре I/O, он также устанавливает запрос на уведомление о соответствующих объектах, встречающих Ваш переданный - в критерии. IOKitLib реализует эту функцию путем вызова IOService addNotification
метод, создающий персистентный обработчик уведомления, который может быть уведомлен относительно событий IOService.
Использовать IOServiceAddMatchingNotification
, однако, необходимо сначала использовать некоторые другие функции в IOKitLib для установки механизма уведомления. Для получения дополнительной информации об этих функциях посмотрите следующий раздел, Настроив и Получив Уведомления. Для схемы шагов Ваше приложение берет, чтобы установить механизм уведомления с помощью цикла выполнения, видеть Получение Уведомлений о Поступлении Устройства и Отбытии.
Установка и получение уведомлений
IOKitLib обеспечивает несколько функций, которые Вы используете, чтобы установить и управлять объектами уведомления:
Принимаете ли Вы решение получить уведомления на цикле выполнения, или порт Маха (использующий цикл выполнения рекомендуемый подход), необходимо сначала создать объект, который может прислушаться к уведомлениям Набора I/O. Чтобы сделать это, Вы используете IONotificationPortCreate
функция, возвращающая объект типа IONotificationPortRef. IOKitLib реализует эту функцию путем выделения получить права на текущем порту Маха, предоставления его, имя IONotificationPort возражает, что Вы передаете в.
Для получения уведомлений на цикле выполнения Вы сначала используете IONotificationPortGetRunLoopSource
функция для получения источника цикла выполнения можно установить на текущем цикле выполнения приложения. В OS X цикл выполнения регистрирует входные источники, такие как порты Маха, и включает поставку событий, таких как статус объекта IOService изменяется, через те источники. Исходный объект цикла выполнения Вы получаете из IONotificationPortGetRunLoopSource
функция имеет тип CFRunLoopSourceRef. (Для получения дополнительной информации о том, как установить источник цикла выполнения на цикле выполнения Вашего приложения, посмотрите Получение Уведомлений о Поступлении Устройства и Отбытии.)
IOKitLib обеспечивает две функции, позволяющие Вам, используют порт Маха, который Вы создаете, на котором можно прислушаться к уведомлениям, а не циклу выполнения. Несмотря на то, что этот метод доступен Вам, рекомендуется использовать более простое к реализации и больше автоматического решения цикла выполнения вместо этого. IONotificationPortGetMachPort
функционируйте возвращает порт Маха, на котором объект IONotificationPortRef может прислушаться к уведомлениям. Когда объект уведомления получает сообщение, Вы передаете сообщение IODispatchCalloutFromMessage
функция для генерации функции обратного вызова связалась с уведомлением.
IONotificationPortDestroy
функция очищает и уничтожает все права, названные переданным - на имя порта (IONotificationPortRef возражают, что Вы получили из IONotificationPortCreate
). Когда Вы больше не хотите получить уведомления, необходимо вызвать эту функцию.
Итерация по согласующим устройствам
Для доступа к соответствующим объектам, поиск функционирует возвраты, Вы используете IOIteratorNext
функция. IOKitLib содержит три функции, воздействующие на io_iterator_t
объекты:
Как подкласс OSIterator, объект IOIterator в ядре определяет методы getNextObject
, isValid
, и reset
. IOKitLib вызывает эти методы в своей реализации IOIteratorNext
, IOIteratorIsValid
, и IOIteratorReset
, соответственно.
IOIteratorNext
просто возвращает ссылку на текущий объект в списке ( io_object_t
объект) и усовершенствования итератор к следующему объекту.
IOIteratorIsValid
возвращает булево значение, указывающее, допустим ли итератор все еще. Иногда, если Реестр I/O изменяется при использовании итератора итератор становится недопустимым. Когда дело обстоит так, IOIteratorIsValid
нуль возвратов и Вы можете сбросить недопустимый итератор к началу списка, использования IOIteratorReset
. Конечно, можно использовать IOIteratorReset
запускаться в начале списка по любой причине, не только потому, что итератор недопустим.
Доступ к реестру I/O
IOKitLib обеспечивает диапазон функций, находящих и предоставляющих информацию об объектах в Реестре I/O. В отличие от функций обнаружения устройств, фокусирующихся на нахождении и доступе к зарегистрированному устройству, возражает, что соответствуют Ваше соответствие словаря, функции Доступа к реестру I/O позволяют Вам просматривать объекты более широко как записи в Реестре I/O, обеспечивая способы свободно переместиться по Реестру I/O и получить информацию о любом объекте в нем. Если Вы незнакомы со структурой Реестра I/O, можно читать больше об этом в Реестре I/O в Основных принципах IOKit. Следующие параграфы обеспечивают сводку.
Реестр I/O является базой динамических данных, получающей соединения всего драйвера и объектов куска, в настоящее время активных в рабочей системе OS X. Можно думать о Реестре I/O, поскольку древовидная структура базировалась в Эксперте по Платформе, драйвере основной логической платы, знающей тип платформы, на которой работает система OS X.
Реестр I/O использует понятие плоскости для описания различных связей с потребителями провайдера между объектами. Плоскость Службы выводит на экран иерархию инстанцирования Реестра I/O: Каждый объект в Реестре I/O является клиентом услуг, предоставленных его родителем, таким образом, соединение каждого объекта с его наследователем в дереве Реестра I/O видимо на плоскости Службы. Другие плоскости выражают связи с потребителями провайдера между объектами, участвующими в определенной иерархии, такой как поток питания от провайдера питания до клиента питания.
Многие функции Доступа к реестру I/O требуют, чтобы Вы передали в параметре, определяющем определенную плоскость. В большинстве случаев Вы, вероятно, укажете комплексную плоскость Службы, но могут быть времена, когда Вы хотите сузить фокус немного. Файл IOKitKeys.h
(в платформе Набора I/O), содержит плоские определения имени, которые Вы используете в своем коде.
IOKitLib обеспечивает функции Доступа к реестру I/O что:
Пересеките Реестр I/O в некотором роде
Предоставьте информацию об определенном объекте в Реестре I/O
Позвольте Вам просматривать Реестр I/O свойства объекта
Позвольте Вам устанавливать свойства в I/O таблица свойства объекта Registy
IOKitLib реализует большинство этих функций путем вызова столь же названных методов IORegistryEntry (см. IORegistryEntry.h
в IOKit
каталог платформы Ядра для больше). Следующие разделы описывают, как Вы используете функции Реестра I/O.
Пересечение Реестра I/O
Когда Вы используете IOServiceGetMatchingServices
функция поиска, Вы получаете итератор, который можно использовать для доступа к каждому объекту в списке соответствия объектов Реестра I/O. Но что, если Вы хотите искать Реестр I/O с помощью некоторых критериев кроме соответствующего словаря? Скажите, например, Вы хотите найти все дочерние элементы (клиенты) определенного объекта, независимо от того, регистрируются ли они в настоящее время в Реестре I/O. Следующие функции предоставляют Вам доступ к родителям и дочерним элементам io_registry_entry_t
объект:
Не удивительно, функции со словом «итератор» на их имена предоставляют Вас io_iterator_t
объект можно передать IOIteratorNext
получить доступ к каждому io_registry_entry_t
объект в списке. IORegistryEntryGetParentIterator
, например, взгляды в указанной плоскости для нахождения всех наследователей переданного - в объекте и возвратах итератор можно использовать для доступа к ним. Поскольку Вы делаете с IOServiceGetMatchingService
и IOServiceAddMatchingNotification
функции, убедиться выпустить возвращенный io_iterator_t
возразите, когда Вы закончены с ним (вспомните, что, выпуская итератор Вы получаете из IOServiceAddMatchingNotification
также отключает то уведомление). Другие две функции, IORegistryEntryGetChildEntry
и IORegistryEntryGetParentEntry
, возвратите первый дочерний элемент или наследователя переданного - в объекте в указанной плоскости.
Для еще более широких поисков можно использовать следующие функции для поиска всего Реестра I/O от любой точки и к любой глубине:
IORegistryCreateIterator
функционируйте возвращается io_iterator_t
объект, начинающийся в корне Реестра I/O и выполняющий итерации по всем его дочерним элементам в указанной плоскости. Точно так же IORegistryEntryCreateIterator
возвраты io_iterator_t
объект, начинающийся в переданном - в io_registry_entry_t
возразите и выполняет итерации или по всем его наследователям или по всем его дочерним элементам в переданном - в плоскости.
Обе этих функции позволяют Вам указывать опцию, говорящую итератору автоматически рекурсивно вызывать в объекты, когда они возвращаются, или только когда Вы вызываете IORegistryIteratorEnterEntry
рекурсивно вызывать в текущий объект. IORegistryIteratorExitEntry
функционируйте отменяет эффект IORegistryIteratorEnterEntry
сбрасывая итератор к текущему объекту, позволяя итератору продолжаться от того, где это кончило. Поскольку его имя подразумевает, IORegistryGetRootEntry
возвраты io_registry_entry_t
объект, представляющий корень Реестра I/O.
Получение информации Об Объектах Реестра I/O
IOKitLib обеспечивает ряд функций, упомянутых ниже, та информация о возврате об определенном объекте Реестра I/O, таких как его имя или путь.
IOKitLib реализует эти функции путем вызова методов IORegistryEntry такой как getName
и getLocation
. Каждая функция возвращает струну до, содержащую имя или расположение объекта. Например, Перечисление 4-4 показывает, как использовать некоторые из этих функций на объекте, представляющем Apple клавиатура USB.
Перечисление 4-4 Используя IORegistryEntryGet
функции
io_service_t device; |
io_name_t devName; |
io_string_t pathName; |
IORegistryEntryGetName(device, devName); |
printf("Device's name = %s\n", devName); |
IORegistryEntryGetPath(device, kIOServicePlane, pathName); |
printf("Device's path in IOService plane = %s\n", pathName); |
IORegistryEntryGetPath(device, kIOUSBPlane, pathName); |
printf("Device's path in IOUSB plane = %s\n", pathName); |
Код в Перечислении 4-4 выводит на экран информацию как следующее:
Device's name = Apple Extended USB Keyboard |
Device's path in IOService plane = IOService:/MacRISC2PE/pci@f2000000/ |
AppleMacRiscPCI/usb@18/AppleUSBOHCI/Apple Extended USB Keyboard@1211000 |
Device's path in IOUSB plane = IOUSB:/IOUSBHubDevice@1200000/Hub in Apple |
Extended USB Keyboard@1210000/Apple Extended USB Keyboard@1211000 |
Если Вы больше интересуетесь тем, существует ли объект в определенной плоскости, чем по ее пути или имени, можно использовать IORegistryEntryInPlane
возвращающаяся функция, TRUE
если объект имеет родителя в плоскости и FALSE
иначе.
Просмотр Свойств Объектов Реестра I/O
Каждый объект в Реестре I/O имеет два словаря, связанные с ним:
Таблица свойства для объекта — если объект является драйвером, это - соответствующий словарь, определяющий одно из водительских лиц (если объект является куском, семейство устройства публикует свойства устройства в таблице свойства куска).
Плоский словарь — этот словарь описывает, как объект подключен к другим объектам в Реестре I/O.
Эти словари являются экземплярами OSDictionary. libkern библиотека C++ определяет контейнерные классы, содержащие примитивные значения, такие как числа и строки и классы набора, содержащие группы из обоих контейнерных объектов и других объектов коллекции. Для просмотра содержания этих объектов в приложении необходимо использовать функции IOKitLib для преобразования набора в ядре или контейнерного объекта (такого как OSDictionary или OSString) к эквивалентному Базовому объекту Основы. В настоящее время только следующие libkern классы доступны как Базовые аналоги Основы:
OSDictionary
OSArray
OSSet
OSSymbol
OSString
OSData
OSNumber
OSBoolean
Следующие функции IOKitLib позволяют Вам получать доступ к свойствам объекта как к Базовым типам Основы:
IORegistryEntryCreateCFProperty
функция создает Базовый контейнер Основы представление значения, связанного с переданным - в ключе свойства. Например, можно получить CFTypeRef к имени файла устройств устройства хранения путем передачи дескриптора устройству ( io_object_t
объект) и ключ kIOBSDNameKey
(определенный в IOBSD.h
) к IORegistryEntryCreateCFProperty
:
CFTypeRef deviceFileName; |
deviceFileName = IORegistryEntryCreateCFProperty(deviceHandle, |
CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0); |
IORegistryEntryCreateCFProperties
функция создает Базовый объект словаря Основы, содержащий переданный - в таблице свойства объекта. После того, как Ваше приложение получает представление CFDictionary таблицы свойства объекта, это может вызвать Базовые функции Основы (такой как CFDictionaryGetValue
и CFNumberGetValue
) получить доступ к значениям словаря.
IORegistryEntrySearchCFProperty
функционируйте ищет переданный - в свойстве, начинаясь с указанного io_registry_entry_t
таблица свойства объекта, и продолжающий или ее родителей или ее дочерние элементы в указанной плоскости. Когда это находит свойство, Вы передали в, это возвращает Базовый контейнерный объект Основы, представляющий свойство.
Когда Вы закончены с Базовым контейнерным объектом Основы, Вы получаете от этих функций, необходимо вызвать CFRelease
на нем.
Поскольку Реестр I/O является базой динамических данных, постоянно обновляющейся, свойства функция такой как IORegistryEntryCreateCFProperties
возвраты представляют снимок состояния Реестра I/O в единственный момент. Поэтому Вы не должны предполагать, что свойства, которые Вы получаете, статичны — если Вы вызываете эти функции многократно в Вашем приложении, можно получить различные результаты каждый раз.
Установка Свойств Объектов Реестра I/O
В дополнение к просмотру свойств объекта в приложении можно также использовать функции IOKitLib для размещения новых свойств в таблицу свойства объекта.
Установка свойств от пространства пользователя подходит для некоторых типов управления устройствами, в частности единственных загрузок данных, такова как загрузка встроенного микропрограммного обеспечения. Этот тип коммуникации ядра пространства пользователя работает, потому что и приложение и в объекте ядра имеют доступ к таблице свойства объекта устройства в Реестре I/O. Конечно, при использовании функций IOKitLib для установки свойств в таблице свойства объекта, важно понять, что Вы только управляете представлением OSDictionary информационного списка свойств объекта, не самого списка свойств.
Перед рассмотрением установки свойств объекта в приложении удостоверьтесь, что ситуация отвечает следующим условиям:
Ваше семейство устройства реализует
setProperties
метод или Вы управляете в драйвере ядра, и в нем, Вы реализуетеsetProperties
метод.Драйвер не должен выделять постоянные ресурсы для завершения транзакции.
Данные не отправили или причинам изменения в водительском состоянии или вызывают единственное, постоянное изменение.
Если приложение передает данные копией, это отправляет только ограниченную сумму, такую как страница или меньше. (Если приложение отправляет данные ссылкой, это может отправить произвольный объем данных.)
IOKitLib обеспечивает четыре функции, позволяющие Вам устанавливать свойства в таблице свойства I/O Registry объекта:
Первые две функции, IORegistryEntrySetCFProperty
и IORegistryEntrySetCFProperties
, родовые функции, устанавливающие или единственное значение свойства или набор значений свойств (обычно в объекте CFDictionary) в указанном io_registry_entry_t
объект. В объекте ядра интерпретирует Базовый контейнерный объект Основы или объект коллекции, как это выбирает.
Если Вы разработаете свое собственное клиентское решение интерфейсного пользователя устройства, то Вы, более вероятно, будете использовать IOConnectSetCFProperty
и IOConnectSetCFProperties
функции для установки свойств. Это вызвано тем, что Вы работаете с io_connect_t
объект, представляющий соединение, которым Вы открылись к объекту в драйвере ядра IOServiceOpen
и эти функции обеспечивают больше управления доступом, чем IORegistryEntrySetProperty
и IORegistryEntrySetProperties
. Для краткого обзора того, как создать соединение с пользовательским клиентом, посмотрите Интерфейсную устройством Разработку.
Определение состояний занятости
IOKitLib включает ряд функций, дающих Вам информацию о состоянии занятости различных объектов IOService и позволяющих Вам ожидать, пока эти объекты больше не заняты:
Поскольку действия, такие как регистрация, соответствие и завершение являются асинхронными, объект IOService в процессе одного из этих действий считают занятым и busyState
стоимость увеличена одной. Когда любое из этих действий заканчивается, IOService’s busyState
значение уменьшено одним. Кроме того, любое время объект IOService busyState
оцените изменения, его провайдер busyState
оцените изменяется на соответствие, что означает, что объект IOService считается занятым, когда любой из его клиентов занят.
Получить состояние занятости частного лица io_service_t
объект, Вы используете IOServiceGetBusyState
функция, которую IOKitLib реализует путем вызова объекта getBusyState
метод.
Можно получить состояние занятости всех объектов IOService путем вызова IOKitGetBusyState
функция. Когда любой из ее клиентов (другими словами, любой объект IOService) занят, как провайдер всех объектов IOService в Реестре I/O, корень плоскости Службы занят. IOKitGetBusyState
функционируйте возвращает состояние занятости корня плоскости Службы, эффективно сообщая Вам о состоянии занятости Реестра I/O в целом.
Можно ожидать, пока объекты не прекращают быть занятыми путем вызова любого IOServiceWaitQuiet
или IOKitWaitQuiet
функции. Обе функции позволяют Вам указывать максимальное время, чтобы ожидать и блокировать обработку вызовов, пока или время не заканчивается или объект, становится незанятым.
Интерфейсная устройством разработка
Если необходимо реализовать и пользовательский клиент в ядре и интерфейсную устройством библиотеку, необходимо считать Аппаратные средства Создания, Доступные в Руководстве по проектированию Драйвера устройства IOKit для всесторонней информации о том, как сделать это. Этот раздел покрывает только сторону пространства пользователя этого процесса, кратко описывая включенные функции IOKitLib.
Несмотря на то, что Вы не можете непосредственно использовать функции IOKitLib, это разделяет, описывает, зная, как они работают, даст Вам некоторое понимание, как сотрудничают интерфейсы устройства и пользовательские клиенты.
Создание соединения ядра пространства пользователя
IOKitLib обеспечивает несколько функций, позволяющих Вам создавать и управлять соединениями с в объектах ядра, обычно пользовательские клиенты. Как с другими функциями, описанными в этом разделе, необходимо использовать их только, когда семейство устройства не предоставляет интерфейсное устройством решение, и Вы решили реализовать и пользовательский клиент в ядре и интерфейс устройства пространства пользователя.
Для приложения для передачи с устройством первая вещь, которую это должно сделать, создают соединение между собой и представлением в объекте ядра устройства. Чтобы сделать это, это создает пользовательский объект клиента.
После того, как это добирается io_service_t
объект, представляющий драйвер устройства (путем вызова IOServiceGetMatchingServices
, например), приложение вызывает IOKitLib IOServiceOpen
функция для создания соединения. IOServiceOpen
функция вызывает io_service_t
объект newUserClient
метод, инстанцирующий, инициализирует и присоединяет пользовательский клиент. В результате вызова IOServiceOpen
, приложение получает io_connect_t
объект (представление пользовательского объекта клиента), что это может использовать с IOKitLib IOConnect
функции.
Например, в проекте SimpleUserClient в качестве примера, часть приложения проекта создает пользовательский клиент с кодом как показанный в Перечислении 4-5.
Перечисление 4-5 , Создающее пользовательский клиент
//Code to get the I/O Kit master port, create a matching dictionary, and get |
//an io_service_t object representing the in-kernel driver is not shown here. |
io_service_t serviceObject; |
io_connect_t dataPort; |
kern_return_t kernResult; |
kernResult = IOServiceOpen(serviceObject, mach_task_self(), 0, &dataPort); |
Приложение уничтожает соединение с пользовательским клиентом с вызовом к IOServiceClose
функция, вызывающая clientClose
метод в пользовательском клиенте. Если по некоторым причинам приложение завершается, прежде чем оно будет в состоянии вызвать IOServiceClose
, пользовательский клиент вызывает clientDied
метод. Как правило, пользовательский клиент реагирует на оба метода путем вызова close
на его провайдере (обычно кусок устройства).
При разработке собственного пользовательского клиента и интерфейсной устройством библиотеки функции IOKitLib, которые Вы, наиболее вероятно, будете использовать, являются четырьмя IOConnectMethod
функции (которые вызывают внешние методы клиента пользователя) и, если Ваш пользовательский клиент может отобразить аппаратные регистры в адресное пространство Вашего приложения, IOConnectMapMemory
и IOConnectUnmapMemory
.
Функции IOConnectMethod
IOConnectMethod
функции используют массивы структур, содержащих указатели на методы для вызова в пользовательском объекте клиента. Пользовательский клиент определяет список методов, которые он реализует в IOExternalMethod
массив. Как правило, эти методы включают пользовательский клиент open
и close
методы и методы, передающие данные между в драйвере ядра и приложением. Использовать IOConnectMethod
функция, приложение передает в io_connect_t
объект, индекс в IOExternalMethod
массив, и, если приложение передает или получает данные, параметры, описывающие общий тип данных (скаляр или структура), число скалярных параметров, размер структур данных и направление (ввод или вывод).
Для открытия пользовательского клиента приложение вызывает любой из IOConnectMethod
функции, передающие в просто io_connect_t
объект, представляющий пользовательский клиент и IOExternalMethod
индекс массива, соответствующий пользовательскому клиенту open
метод. Поскольку приложение не передает или получает любые данные в этой точке, оставление двумя параметрами передало IOConnectMethod
функция является нулем. Например, код ниже шоу, как приложение в проекте SimpleUserClient использует io_connect_t
возразите, что это получило в Перечислении 4-5 для открытия его пользовательского клиента:
//kMyUserClientOpen is one of the enum constants the SimpleUserClient |
//project uses as indexes into the IOExternalMethod array. |
kernResult = IOConnectMethodScalarIScalarO(dataPort, kMyUserClientOpen, |
0, 0); |
Для передачи невведенных данных назад и вперед через границу пользовательского ядра приложение использует один из IOConnectMethod
функции в Таблице 4-2, в зависимости от типа данных и направления потока данных.
Функция | Описание |
---|---|
Один или более скалярных входных параметров, один или несколько скалярных выходных параметров | |
Один или более скалярных входных параметров, одна структура вывела параметр | |
Один или более скалярных входных параметров, одна структура ввела параметр | |
Одна структура ввела параметр, один выходной параметр структуры |
IOConnectMethod
функции разработаны для принятия списков аргумента переменной, в зависимости от типа данных и направления, которое Вы выбираете. После первых двух параметров — io_connect_t
возразите и индекс массива метода — является некоторой комбинацией параметров, идентифицирующих:
Число скалярных значений ввода или вывода
Размер структуры ввода или вывода
Скалярные значения ввода или вывода
Указатель на структуру ввода или вывода
Приложение в SimpleUserClient, например, использует IOConnectMethodScalarIStructureI
функционируйте как показано в Перечислении 4-6.
Перечисление 4-6 , Запрашивающее I/O с IOConnectMethodScalarIStructureI
функция
//MySampleStruct is defined in the header file both the user client |
//and the application include and consists of two integer variable |
//declarations. |
MySampleStruct sampleStruct = {586, 8756}; //Random numbers. |
int sampleNumber = 15; //Random number. |
IOByteCount structSize = sizeof(MySampleStruct); |
kern_return_t kernResult; |
kernResult = IOConnectMethodScalarIStructureI(dataPort, // from IOServiceOpen |
kMyScalarIStructImethod, // method index |
1, // number of scalar input values |
structSize, // size of input structure |
sampleNumber, // scalar input value |
&sampleStruct // pointer to input structure |
); |
Отображающие память функции
Если Ваш драйвер устройства имеет полный PIO (Запрограммированный ввод/вывод), управление памятью и Ваше устройство не требуют использования прерываний, можно записать специальное применение, перемещающее большие объемы данных в и от устройства, с помощью IOConnectMapMemory
и IOConnectUnmapMemory
функции. Например, приложение кадрового буфера может использовать эти функции для обработки больших сумм встроенной памяти, которая должна быть доступной от пространства пользователя. IOConnectMapMemory
функция позволяет пользовательскому процессу совместно использовать память с в драйвере ядра путем отображения той же памяти в оба процесса.
Когда пользовательский процесс вызывает IOConnectMapMemory
, это передает в, среди других параметров, указателя на область в ее собственном адресном пространстве, которое будет содержать расширенную память. Вызов к IOConnectMapMemory
вызывает вызов пользовательского клиента clientMemoryForType
метод. Пользовательский клиент реализует этот метод путем создания объекта IOMemoryDescriptor, что регистрируются спины отображение на аппаратные средства. Пользовательский процесс получает виртуальную память vm_address_t
объект, содержащий адрес расширенной памяти и a vm_size_t
объект, содержащий размер отображения. В этой точке пользовательский процесс может свободно записать в и читать из аппаратных регистров.
Когда интерфейс пользовательского процесса или устройства закончен, выполнив I/O с расширенной памятью, он должен вызвать IOConnectUnmapMemory
удалить отображение.
Управление соединением ядра пространства пользователя
Остающееся IOConnect
функции в IOKitLib прежде всего предназначаются, чтобы помочь Вам управлять своим пользовательским соединением ядра пространства пользователя. Как с другим IOConnect
функции, Вы не должны использовать их с Набором I/O предоставленные семьей или сторонние интерфейсы устройства, потому что они воздействуют непосредственно на io_connect_t
объект, представляющий соединение, обходя существующий интерфейс устройства.
IOKitLib содержит следующие функции для управления io_connect_t
объект:
IOConnectAddClient
функция создает соединение между двумя пользовательскими объектами клиента в ядре путем вызова первого пользовательского клиента connectClient
метод. Можно использовать эту функцию в маловероятном случае, что у Вас есть два пользовательских клиента, которые должны быть в состоянии связаться.
Поскольку их имена предлагают, IOConnectAddRef
и IOConnectRelease
скорректируйте подсчет ссылок на переданном - в io_connect_t
объект.
IOConnectGetService
функционируйте возвращается io_service_t
объект, представляющий IOService, возражает на который переданный - в io_connect_t
объект был открыт. IOKitLib реализует эту функцию путем вызова пользовательского клиента getService
метод.
Для идентификации порта Маха, на котором можно получить специфичные для семьи уведомления (типы уведомления, не интерпретируемые Набором I/O) Вы используете IOConnectSetNotificationPort
функция. Вы передаете в, среди других параметров, io_connect_t
объект, представляющий пользовательское соединение клиента и a mach_port_t
объект, представляющий порт Маха, на котором Вы хотите получить уведомления. IOKitLib реализует эту функцию путем вызова пользовательского клиента registerNotificationPort
метод.