Обзор архитектуры
Поскольку Вы можете с любой сложной системой, можно смотреть на проект Набора I/O от различных углов и при различных гранулярностях. Эта глава представляет Вас более важным архитектурным элементам и концептуальным доменам Набора I/O:
Аппаратное моделирование, разделение на уровни объектов драйвера и роли, которые играют семьи, драйверы и куски
Среда выполнения драйверов устройств
Реестр Набора I/O и Каталог I/O
Соответствие драйвера
Иерархия классов Набора I/O
Интерфейсы устройства
Следует иметь в виду, что эта глава является обзором, и таким образом, обсуждение, которое она посвящает каждой из этих тем, преднамеренно кратко. Более поздние главы затрагивают большинство этих тем более подробно. В случае интерфейсов устройства документ, Получающий доступ к Аппаратным средствам Из Приложений, описывает технологию очень подробно.
Разделение на уровни драйвера
Центральный к проекту Набора I/O модульная, многоуровневая архитектура среды выполнения, моделирующая аппаратные средства системы OS X путем получения динамических отношений среди многократных частей — аппаратного и программного обеспечения — вовлеченный в соединение I/O. Уровни соединения, включая объекты драйвера и семьи, из которых эти объекты являются элементами, сложены в связях с потребителями провайдера.
Цепочка соединенных служб или устройств запускается с логической платы компьютера (и драйвер, управляющий ею), и, посредством процесса открытия и «соответствия», расширяет соединение с помощью уровней объектов драйвера, управляющих системными шинами (PCI, USB, и т.д.) и отдельные устройства и службы, присоединенные к этим шинам.
Можно просмотреть разделение на уровни объектов драйвера в рабочей системе OS X с помощью приложения Проводника Реестра I/O, включенного в версию разработчика OS X. Версия разработчика также включает версию командной строки приложения, ioreg
, то, что можно работать в Окне терминала для отображения текущей Информации о реестре I/O.
Этот раздел исследует многоуровневую архитектуру Набора I/O и описывает элементы преобладающего компонента: семьи, драйверы и куски.
Семьи и драйверы
Семья I/O Kit является одним или более классами C++, реализующими абстракции программного обеспечения, характерные для всех устройств определенного типа. Набор I/O имеет семьи для протоколов шины (таких как Параллель SCSI, USB и FireWire), для хранения (диск) устройства, для сетевых служб (включая Ethernet), для устройств интерфейса пользователя (таких как мыши, клавиатуры и джойстики), и для узла других устройств.
Драйвер становится элементом семьи посредством наследования; водительский класс является почти всегда подклассом некоторого класса в семье. Будучи элементом семьи, драйвер наследовал структуры данных (переменные экземпляра) и способы поведения, которые характерны для всех элементов семьи. Например, все контроллеры SCSI имеют определенные вещи, которые они должны сделать, такие как сканирование шины SCSI; семья SCSI Parallel определяет и реализует эту функциональность сканирования. Таким образом Вы не должны включать код сканирования в свой новый драйвер контроллера SCSI (если Вы не требуете различной реализации сканирования).
Большая часть разработки Набора I/O включает пишущие определенные классы драйвера, каждый из которых наследовался от суперкласса в семье, обеспечивающей функциональность, которой требует драйвер. Драйвер для контроллера Ethernet, например, наследовался от суперкласса IOEthernetController в семье Network. Объем водительского взаимодействия с его собственной семьей включает функции членства реализации, которые вызывает семья. Это обычно клиентская конфигурация и запросы I/O. Некоторые семьи также определяют объекты и функции для Вашего драйвера для использования. Точный характер этих объектов и функций зависит от семьи Ваши работы драйвера с.
Однако драйвер обычно работает с двумя семьями. В дополнение к семье драйвер является элементом, класс драйвера должен связаться с куском, опубликованным семьей для шины, или протоколировать устройство, присоединен. Кусок (как Драйверы и Куски объясняет подробно) является объектом, определяющим точку доступа и канал передачи для данного протокола. Семья (обычно представляющий шину, такую как PCI или USB) действует как водительский провайдер через кусок, который это создает. Драйвер использует кусок, чтобы присоединить в Реестр I/O и связаться с его устройством. Как пример, драйвер Ethernet PCI использовал бы IOPCIDevice
кусок от семьи PCI, чтобы присоединить к и связаться по шине PCI. Водительское основное взаимодействие с куском включает выпуск запросов или команды на любой шине, из которой кусок является клиентом. Драйвер устройства SCSI, например, выпускает блоки команды SCSI и результаты проверок через кусок.
Для больше на семьях, особенно природа и состав суперклассов в семье, посмотрите Классы семьи Набора I/O
Драйверы и куски
Набор I/O поддерживает два широких типа объектов драйвера. Первым является кусок, объект, определяющий точку доступа и канал передачи, обычно для данного протокола, такого как PCI, USB или Ethernet. Второй тип является определенным драйвером для отдельного устройства или службы. Определенный драйвер связывается с аппаратными средствами, через кусок, для выполнения операций I/O. И драйверы и куски в Наборе I/O должны наследоваться от класса IOService.
Драйвер является объектом Набора I/O, управляющим определенной частью аппаратных средств. Драйверы записаны как расширения ядра и обычно устанавливаются в папке Extensions (в /System/Library/Extensions
.) См. Обзор Расширения ядра в Руководстве по программированию Ядра для получения дополнительной информации о создании и установке расширений ядра.
Когда драйвер выбран для устройства, но прежде чем он будет загружен в ядро (как расширение ядра), все требуемые семьи — с точки зрения суперклассов и их зависимостей — загружаются для обеспечения общей функциональности для драйвера и других его типа. (Конечно, если эти семьи были уже загружены, этот шаг не необходим.) После того, как все требования для драйвера удовлетворяются, драйвер загружают и инстанцируют как объект. Посмотрите Анатомию Соединения I/O для иллюстрации этого процесса.
Кусок является объектом Набора I/O, представляющим канал передачи для устройства или логической службы и добивающимся доступа к устройству и службе. Например, кусок мог представлять шину, диск, раздел диска, графический адаптер или клавиатуру. Это могло бы помочь думать о куске как о представлении программного обеспечения слота устройства или коннектора. Куски также предоставляют услуги, такие как арбитраж, управление питанием и драйвер, соответствующий (см. Реестр I/O и Каталог I/O).
Куски действуют как мосты между двумя драйверами и, расширением, между двумя семьями. Драйвер связывается с куском (и семья куска) как ее клиент и, через ее семью, может опубликовать кусок, находящий (путем соответствия) драйвер, для которого это - провайдер. Обычно драйвер публикует один кусок для каждого отдельного устройства или службы, которой это управляет; однако, когда драйвер поддерживает определенную часть аппаратных средств, это может действовать как свой собственный кусок.
Анатомия Соединения I/O
Многоуровневая архитектура Набора I/O моделирует цепочку соединений между аппаратными шинами и устройствами системы, собирая общую функциональность в классы, с которыми может взаимодействовать Ваш драйвер. Каждый уровень является клиентом уровня ниже его и провайдера служб к уровню выше его. Широкие группировки уровней, определенных семьями I/O Kit, определяют функциональность, характерную для общего типа провайдера I/O, такого как сети или устройства шины PCI.
Рассмотрите рисунок 2-1, иллюстрирующий типичное разделение на уровни клиента и объектов провайдера для основанного на PCI драйвера контроллера Ethernet в семье Network.
Поскольку эта схема показывает, Ваш драйвер обычно соответствует между двумя семьями, наследовавшимися от класса в семье верхнего уровня и использующими службы семьи нижнего уровня. В случае контроллера Ethernet драйвер участвует в штабеле объектов C++, включающих экземпляры классов от семей PCI и сетей:
IONetworkStack (объект управления интерфейса) | Подключения Набор I/O возражают против BSD сетевым средствам. |
IOEthernetInterface (кусок) | Управляет независящей от устройств передачей данных и приемом. |
Драйвер контроллера (драйвер) | Управляет контроллером Ethernet через объект IOPCIDevice. Этот объект наследовался от сетевого класса семьи под названием IOEthernetController. |
IOPCIDevice (кусок) | Матч-пойнт для контроллера; обеспечивает основное взаимодействие шины PCI для контроллера. |
IOPCIBridge (драйвер) | Управляет шиной PCI. (Другие объекты предоставляют услуги IOPCIBridge; их определенные идентификационные данные зависят от аппаратной конфигурации.) |
Другой способ смотреть на штабель объектов драйвера в типичном соединении I/O состоит в том, чтобы рассмотреть штабель с динамической точки зрения. Другими словами, что происходит, когда система OS X обнаруживает новое устройство, присоединенное к нему? Как штабель объектов драйвера создан? Для этого давайте использовать пример диска диска SCSI; общий порядок создания или открытия на рисунке 2-2 слева направо.
Это число иллюстрирует, как драйвер диска SCSI, элемент Семейства систем хранения, подключен к шине PCI. Поскольку каждое конкретное соединение сделано, недавно создаваемый драйвер или кусок также добавляются к Реестру I/O (описанный в Реестре I/O и Каталоге I/O). Цепочка соединений имеет место на нескольких шагах:
Драйвер контроллера шины PCI, элемент семьи PCI, обнаруживает устройство PCI и объявляет о его присутствии путем создания куска (
IOPCIDevice
).Кусок идентифицирует (соответствует) надлежащий драйвер устройства — в этом случае, драйвер контроллера SCSI — и запрашивает, чтобы он был загружен. Загрузка драйвера контроллера SCSI вызывает семью SCSI Parallel и все семьи, что это зависит от, чтобы быть загруженным также. Драйверу контроллера SCSI дают ссылку на
IOPCIDevice
кусок.Драйвер контроллера SCSI, который является клиентом семьи PCI и провайдером служб помощи семьям Параллели SCSI, сканирует шину SCSI для устройств, которые могли бы быть клиентами этих служб. После нахождения такого устройства (диск), драйвер объявляет о присутствии устройства путем создания куска (
IOSCSIDevice
).Кусок, путем прохождения через соответствующей процедуры, находит драйвер устройства (дисковый драйвер), который является подходящим для устройства и запрашивает, чтобы был загружен этот драйвер. Загрузка дискового драйвера вызывает Семейство систем хранения и все семьи, что это зависит от, чтобы быть загруженным также. Дисковый драйвер является теперь клиентом семьи SCSI Parallel и участником Семейства систем хранения. Дисковому драйверу дают ссылку на
IOSCSIDevice
кусок.
Во многих случаях приложения и другие программы «пространства пользователя» могут использовать интерфейсную устройством технологию Набора I/O для дисковых устройств (включая устройства массового хранения), устраняя потребность в резидентном ядром драйвере. Посмотрите Управляющие устройства Извне Ядра для обзора этой сменной технологии.
Среда выполнения драйверов устройств
Набор I/O предоставляет среде выполнения несколько мощных функций для писателей драйвера, включая:
Динамическая, многоуровневая архитектура драйвера, позволяющая драйверам быть загруженными и разгруженными в любое время и задержки, резервируя дорогостоящие системные ресурсы, пока они не необходимы
Стандартные средства для управления данными во время общих операций I/O
Устойчивая система для защиты доступа к ресурсам драйвера во время операций I/O, освобождающего писателей драйвера от необходимости записать их собственный код, чтобы включить и отключить прерывания и управлять, соединяет водительские частные ресурсы
Доступ к службам в libkern библиотеке C++ (на котором базируется сам Набор I/O) для управления наборами, выполните атомарные операции и значения подкачки байта для использования на различных видах аппаратных средств
Следующий раздел суммирует каждую из этих функций.
Функции во время выполнения
Драйверы Набора I/O могут быть загружены и разгружены или активированы и деактивированы в любое время через события, инициируемые программным обеспечением — как тогда, когда сетевые стеки принесены вверх и вниз — и аппаратными средствами — как тогда, когда USB-устройство добавлено к или удалено из шины. Почти все драйверы должны работать в контексте динамично изменяющейся системы. Набор I/O делает это проще путем определения стандартного жизненного цикла для объектов драйвера. Путем реализации маленького набора функций полученных в итоге в Общих Классах Набора I/O, драйвер может корректно обработать дополнение и демонтаж устройств и служб, а также изменений, вызванных системой управления питанием.
Почти все операции I/O требуют той же подготовки в OS X:
Проводное соединение памяти вниз, таким образом, это не может быть разбито на страницы во время операций I/O
Здание рассеивается/собирает списки, описывающие буферы данных, чтобы читать или записать
Набор I/O обеспечивает ряд служебных классов, чтобы помочь драйверам подготовить память к операциям I/O, и создавать рассеиваются/собирают списки, включая классы IOMemoryDescriptor и IOMemoryCursor. Для получения дополнительной информации об этих средствах см., что глава Управляет Данными
Драйверы, работающие в многопоточной системе, должны быть в состоянии защитить свои ресурсы от повторно используемого или параллельного доступа. Набор I/O включает маленький набор классов с этой целью. Объект цикла работы выполняет специализированный поток и управляет механизмом пропускания для эксклюзивного доступа к данным. Другие объекты, названные источниками событий, используют механизм пропускания для сериализации вызовов функции что доступ критические ресурсы, закрывая логический элемент цикла работы прежде, чем вызвать функцию. Для получения дополнительной информации о циклах работы и источниках событий, см., что глава Обрабатывает События
libkern библиотека C++, на которой базируется сам Набор I/O, предоставляет услуги, обычно необходимые драйверам, включая:
Арифметические и логические операции, которые, как гарантируют, будут атомарными
Свопинг байта значений между форматами с прямым порядком байтов и с обратным порядком байтов
Классы для общих наборов данных, таких как строки, массивы и словари
Для получения дополнительной информации о libkern классах посмотрите Классы OS, а также libkern справочную документацию, установленную с пакетом Разработчика OS X.
Ограничения программирования ядра
Код ядра всегда считается резидентным объектом в физической памяти и не может быть разбит на страницы системой виртуальной памяти. Это делает ресурсы ядра намного более дорогими, чем ресурсы прикладной программы. Ваш драйвер должен находиться в ядре если:
Это берет основные прерывания (когда это должно жить в ядре),
Его основной клиент находится в ядре; например, драйверы массового хранения, потому что штабели файловой системы находятся в ядре
Драйверы для дисков, сетевых контроллеров, и клавиатур, например, находятся в ядре. Если Ваш драйвер только иногда используется одной программой пространства пользователя за один раз, это должно быть загружено программой и находиться в нем. Драйверы для таких устройств как сканеры и принтеры находятся в программах пространства пользователя, с помощью интерфейсного устройством механизма Набора I/O для передачи с устройствами. Для получения дополнительной информации об интерфейсах устройства посмотрите Управляющие устройства Извне Ядра
Даже если Ваш драйвер находится в ядре, необходимо минимизировать сумму резидентного ядром кода и сумму обработки сделанного тем кодом. Например, специальное применение, управляющее управляемым прерыванием устройством, должно предоставить драйвер, помещающий минимальный код в ядро, должен был обслужить прерывание, сделать доступные данные его клиенту, затем возвратиться. По дополнительным причинам быть осторожными о программировании в ядре, посмотрите, что действительно ли необходимо Программировать в Ядре?
Если Ваш драйвер должен находиться в ядре, необходимо знать о следующих проблемах:
Самое главное ядро является единственной программой — нет никакой защиты памяти между Вашим драйвером и остальной частью ядра. Резидентный ядром драйвер, ведущий себя плохо, может разрушить или подвесить операционную систему.
Более тонкая проблема - то, что штабели вызова функции в ядре ограничиваются 16 КБ. Бойтесь объявлять большие локальные переменные в функциях. Каждый раз, когда возможно, необходимо предварительно выделить буферы и снова использовать их.
Резидентные ядром драйверы имеют полный доступ к интерфейсам программирования ядра. Однако из-за их низкого уровня работы, драйверы должны использовать только вызовы Маха и не вызовы BSD. Много частей кода ядра BSD не в настоящее время безопасны для многопоточности или многопроцессорной обработки. В любом случае драйверы редко должны выполнять вызовы Маха непосредственно, поскольку Набор I/O обеспечивает интерфейсы для большей части функциональности уровня ядра, необходимой драйверу.
Реестр I/O и Каталог I/O
Реестр I/O является базой динамических данных, записывающей сеть объектов драйвера, участвующих в аппаратных соединениях в системе OS X, и отслеживающей связи с потребителями провайдера среди тех объектов. Драйвер устройства должен быть зарегистрирован в Реестре I/O для участия в большинстве служб I/O Kit.
Реестр I/O является критической частью Набора I/O, потому что это поддерживает динамические функции операционной системы, позволяющей пользователям добавлять или демонтировать устройства (особенно FireWire или USB-устройства) к и от рабочей системы и сразу иметь их доступный без потребности в перезагрузке. Поскольку аппаратные средства добавляются, система автоматически находит и загружает необходимые драйверы и обновляет Реестр I/O для отражения новой конфигурации устройства; когда аппаратные средства демонтированы, надлежащие драйверы разгружены, и Реестр обновляется снова. Реестр всегда находится в системной памяти и не сохранен на диске или архивируется между начальными загрузками.
Реестр I/O структурирует свои данные как инвертированное дерево. Каждый объект в древовидных убываниях от родительского узла и может иметь один или несколько дочерних узлов; если это - «листовой» узел, это не имеет никаких дочерних элементов. Почти каждый узел в дереве представляет объект драйвера: кусок или фактический драйвер. Эти объекты должны наследоваться от класса IORegistryEntry (который является суперклассом IOService, суперклассом всех классов драйвера). Центральная характеристика объектов IORegistryEntry является списком связанных свойств. Эти свойства отражают индивидуальность, используемую в драйвере, соответствующем (см., что Драйвер Соответствует), и иначе добавьте информацию о драйвере. Свойства, полученные в Реестре, происходят из каждого водительского информационного списка свойств, файла в драйвере KEXT, содержащий пары ключ/значение, описывающие водительские характеристики, настройки и требования.
Другая база динамических данных, Каталог I/O, работает в тесном сотрудничестве с Реестром I/O. Каталог I/O поддерживает записи для всех доступных драйверов в системе. Когда кусок обнаруживает устройство, он запрашивает список всех драйверов семейства устройства из Каталога I/O.
Можно исследовать Реестр I/O с помощью приложения Проводника Реестра I/O и ioreg
инструмент командной строки, оба включенные в пакет Разработчика OS X. Можно также программно исследовать и управлять свойствами Ключей реестра с помощью функций членства класса IORegistryEntry. Из приложений и других программ в пространстве пользователя, можно искать и информация о драйвере доступа в Реестре I/O с помощью APIs в платформе Набора I/O.
Для больше о Реестре I/O и Каталоге I/O видят главу, Реестр I/O Для получения дополнительной информации о классе IORegistryEntry видит Динамическую Регистрацию Драйвера (IORegistryEntry) в главе “Базовые классы”
Соответствие драйвера
Первичная функция кусков должна предоставить соответствие услуг, соответствуя драйверы к устройствам. В отличие от этого в Mac OS 8 и 9, драйверы не загружаются автоматически просто, потому что они установлены. В OS X драйвер должен сначала быть соответствующим к существующему устройству, прежде чем сможет быть загружен тот драйвер.
Драйвер, соответствующий, является процессом Набора I/O, в котором кусок, после обнаружения определенного устройства, ищет драйвер или драйверы большинство подходящее для того устройства. Для поддержки соответствия драйвера каждый драйвер устройства определяет один или несколько personalitiesthat, указывают виды устройств, которые это может поддерживать. Эта информация хранится в словарях XML, определенных в информационном списке свойств в водительском пакете. Значения словаря указывают, является ли драйвер кандидатом на определенное устройство.
Когда кусок обнаруживает устройство, Набор I/O находит и загружает драйвер для куска в трех отличных фазах, с помощью отнимающего процесса, пока не найден успешный кандидат. Фазы соответствия:
Класс, соответствующий — устраняет драйверы неправильного класса устройства.
Пассивное соответствие — исследует каждого остающегося водительскими лицами для свойств, определенных для устройства, устраняя те не соответствующие драйверы.
Активное соответствие — остающиеся кандидаты драйвера зондируют устройство, чтобы проверить, что они могут управлять им.
То, когда соответствующий драйвер найден, его код загружается, и экземпляр основного класса перечислен в индивидуальности, создается. В этой точке начинается водительский жизненный цикл. Посмотрите Жизненный цикл Объекта Драйвера в главе “Базовые классы” для подробных данных.
Для детального обсуждения лиц драйвера и процесса соответствия, см. главу Соответствие Устройства и Драйвер
Иерархия классов Набора I/O
Набор I/O охватывает десятки классов C++ и является самостоятельно расширением libkern библиотеки C++, основы для загружаемых модулей ядра. Взятый вместе, Набор I/O и libkern, казалось бы, сформировали бы forbiddingly большую и сложную иерархию классов. Все же существенная структура той иерархии довольно проста, поскольку рисунок 2-3 иллюстрирует.
Можно разбить расширенную иерархию классов Набора I/O на три широких группировки:
Классы libkern (иногда называемый классами OS из-за их префикса «OS»)
Базовые классы Набора I/O и классы помощника
Классы семей I/O Kit
Для получения информации о том, где двоичные файлы и заголовочные файлы libkern и библиотеки I/O Kit установлены, дополнительную информацию см. в Платформах и Библиотеках по функциям и интерфейсам базовых классов в этой иерархии — OSObject, OSMetaClass, IORegistryEntry, и IOService — видят Базовые классы
Классы OS
Набор I/O создается поверх libkern библиотеки C++; то есть корневой суперкласс для I/O, Специфичными для набора классами является IORegistryEntry, наследовавшийся от OSObject libkern. Как Набор I/O, libkern записан в подмножестве C++, подходящего для использования в загружаемых модулях ядра. В частности libkern среда C++ исключает обработку исключений C++ и Информацию о типах во время выполнения (RTTI) средства. Вместо этого базовые классы OS реализуют подходящий эквивалент функции RTTI, среди прочего.
В корне расширенной иерархии класс OSObject, и тесно связанный с этим классом класс OSMetaClass. Все другие классы OS являются классами «помощника» для таких вещей как наборы и другие контейнеры данных. Следующее суммирует роли эти классы игра:
OSMetaClass реализует информацию о типах во время выполнения (RTTI) механизм, включает определенную степень объектного самоанализа и поддерживает динамическое распределение объектов, полученных из OSObject именем класса.
Функции APIs OSObject подсчета ссылок (
retain
иrelease
), управление памятью сохраненных объектов и автоматическое избавление от объектов, когда они больше не необходимы. OSObject также обеспечивает динамическую реализацию по умолчаниюinit
иfree
методы.Контейнеры данных OS являются подклассами OSObject, экземпляры которого инкапсулируют различные типы значений данных (такие как булевские переменные, числа, строки) и реализуют и выполняют итерации по наборам, таким как массивы и словари.
Контейнеры данных OS приблизительно соответствуют свои дубликаты пространства пользователя, Базовые контейнеры Основы, и на имя и на поведение. Поскольку характеристики OS и Базовых Фундаментальных классов так подобны, система может легко преобразовать Базовый тип Основы в тип OS и наоборот. Например, объект CFArray преобразовывается в OSArray при пересечении границы пользовательского ядра.
Классы OS обычно полезны для всего кода, записанного для ядра, не просто драйверов устройств. Например, реализация расширений ядра сетевые службы или файловые системы может также использовать в своих интересах эти классы. OSObject в частности является существенным общим суперклассом для кода ядра. Для одного модуля ядра (KMOD) к ссылочным объектам, создаваемым другим KMOD, объекты должны в конечном счете произойти из OSObject. Большинство классов Набора I/O предполагает, что раздаваемые объекты получены из OSObject.
При портировании существующего кода C++ на Набор I/O Вы не обязаны использовать классы OS. Но если Вы решите воздержаться от функций, которые эти классы обеспечивают, такие как подсчет ссылок или контейнеры данных, то необходимо будет, вероятно, реализовать их сами.
Для больше на OSObject и классах OSMetaClass, посмотрите libkern Базовые классы в главе “Базовые классы”
Общие Классы Набора I/O
Средняя группа расширенной иерархии классов включает базовые классы Набора IO — IORegistryEntry и IOService — и ряд классов помощника для управления ресурсами, управления данными, и потока и элемента управления вводом. Эта группа классов Набора I/O названа «общей», потому что все классы драйвера устройства могут потенциально использовать их.
Корневым классом иерархии Набора I/O является IORegistryEntry; на основании наследования от IORegistryEntry объект Набора I/O может быть узлом в Реестре I/O и иметь одну или более таблиц свойства (лица драйвера) связанный с ним. IORegistryEntry реализует много опций:
Это управляет соединением в Реестр через водительское
attach
иdetach
точки входаЭто управляет таблицами свойства, определяющими лица драйвера, использующие объекты OSDictionary
Это реализует блокировку в Реестре, позволяя обновления Реестру быть сделанным атомарно
IOService является единственным прямым подклассом IORegistryEntry. Почти все суперклассы семьи I/O Kit наследовались, прямо или косвенно, от IOService. Самое главное IOService указывает жизненный цикл драйверов устройств в динамической среде выполнения. Посредством соответствия пар виртуальных функций — такой как init
/free
, start
/stop
, и open
/close
— IOService определяет, как объекты драйвера инициализируют себя, присоединяются в Реестр I/O, выполняют все необходимые выделения, и затем инвертируют эффекты этих действий в надлежащем порядке. Для поддержки его управления жизненными циклами драйвера IOService предоставляет соответствие услуг (помогающий с зондированием, например) и инстанцирует драйверов на основе существования провайдера. Кроме того, IOService включает функции членства, которые полезны в различных целях, включая:
Управление питанием
Прерывания устройства (регистрация, нерегистрация, включение, порождение, и т.д.)
Для больше на IORegistryEntry и классах IOService, посмотрите Базовые классы Набора I/O в главе “Базовые классы”
Большинство классов помощника Набора I/O имеет несколько функций, связанных со средой выполнения драйверов устройств:
Реализовывая циклы работы и источники событий (прерывания, таймеры и команды) вместе со связанными блокировками и очередями
Реализация курсоров памяти и дескрипторов памяти для управления данными, вовлеченными в передачи I/O
Для больше на классах помощника Набора I/O, см., что главы Обрабатывают События и Управляют Данными
Классы семьи Набора I/O
Большинство драйверов является экземплярами подкласса класса в семье I/O Kit; классы семьи, в свою очередь, будьте склонны быть подклассами IOService. Ваш класс драйвера должен быть прямым подклассом самого надлежащего класса семьи для драйвера, который Вы пытаетесь записать. Например, если Вы пишете драйвер контроллера Ethernet, Ваш класс драйвера должен быть подклассом IOEthernetController, не IONetworkController (суперкласс IOEthernetController).
Набор I/O имеет более чем дюжину семей, каждого с его собственным набором классов; эти семьи включают следующее:
ADB
ATA и ATAPI
Аудио
FireWire
Графика
HID (устройства интерфейса пользователя)
Сеть
Плата ПК
PCI и AGP
SBP-2
Архитектурная модель SCSI
Параллель SCSI
Последовательный
Запоминающие устройства.
USB
Apple добавит дополнительные семьи, поскольку они разрабатываются. Если Вы требуете семьи для устройства, и это в настоящее время не поддерживается, можно попытаться писать собственные классы семьи. Однако не предполагайте, что новая семья требуется, если Вы в настоящее время не существуете. Во многих случаях класс IOService предоставляет все услуги, которых требует драйвер; такие драйверы «семьи меньше» могут поддерживать много устройств, которые являются определенными для определенных поставщиков. Для получения дополнительной информации о семьях см. главу семьи Набора I/O и приложение Ссылка семьи Набора I/O
Управляющие устройства извне ядра
Возможно, одна из более востребованных функций OS X является неприкосновенным разделением, которое это осуществляет между виртуальными адресными пространствами процессов. Если трудоемкие приготовления не сделаны для общей памяти, один процесс не может непосредственно коснуться данных, отображенных на адресном пространстве другого процесса. Это разделение улучшает устойчивость и надежность системы путем предотвращения памяти trashers и подобных раздражений от перевода в нерабочее состояние процессов.
Еще более важный разделение между адресными пространствами ядра и всех других процессов, которые, как иногда говорят, (с точки зрения ядра) населяют «пространство пользователя». Если приложение или другая программа в пространстве пользователя так или иначе нарушают адресное пространство ядра, целая система может прибыть, отказывая вниз. Для создания этого разделения между ядром и пространством пользователя еще более воздухонепроницаемым программы в пространстве пользователя не могут даже непосредственно вызвать ядро APIs. Они должны сделать системные вызовы (косвенно) ядра доступа APIs.
Иногда, однако, программа в пространстве пользователя должна управлять или сконфигурировать устройство, и таким образом нужна в доступе к службам I/O Kit в ядре. Например, игра, возможно, должна была бы установить глубину монитора или громкость звука, или резервная диском программа, возможно, должна была бы действовать как драйвер для лентопротяжного устройства. Другие примеры приложений, которые должны так или иначе взаимодействовать с ядром для управления аппаратными средствами, включают тех, которые работают или данные интерпретации от сканеров, джойстиков и цифровых фотоаппаратов.
Для ответа на это требование Набор I/O включает два механизма: интерфейсы устройства и узлы устройства POSIX. Через сменную архитектуру и четко определенные интерфейсы, интерфейсный устройством механизм позволяет программе в пространстве пользователя связаться с куском в ядре, которое является надлежащим типу устройства, которым это хочет управлять. Через кусок программа получает доступ к службам I/O Kit и к самому устройству. Для хранения, последовательных, и сетевых устройств, приложения могут получить информацию, в которой они нуждаются от Набора I/O до доступа и управляют этими устройствами с помощью POSIX APIs.
Следует иметь в виду, что существуют некоторые службы помощи семьям, с которыми соединяет интерфейсом I/O, который Кит отказывается экспортировать в пространство пользователя как устройство; эти службы доступны только в ядре. Примером является семья PCI. По причинам устойчивости и безопасности, запрещается внешний доступ к ресурсам PCI. Приложение I/O Ссылка семьи Кита идентифицирует семьи то устройство экспорта интерфейсы.
Этот раздел суммирует информацию в Доступе к Аппаратным средствам Из Приложений. Обратитесь к этому документу для полного описания интерфейсов устройства и как использовать их.
Интерфейсный устройством механизм
Интерфейс устройства является сменным интерфейсом между ядром и процессом в пространстве пользователя. Интерфейс соответствует сменной архитектуре, определенной Базовыми Службами Плагина Основы (CFPlugIn), который, в свою очередь, совместимо с основами Объектной модели компонентов (COM) Microsoft. В модели CFPlugIn действия ядра как сменный узел с его собственным набором четко определенных интерфейсов Набора I/O и платформа Набора I/O обеспечивают ряд плагинов (интерфейсы устройства) для приложений для использования.
Концептуально, интерфейс устройства одновременно покупает и продает границу между пространством пользователя и ядром. Это обрабатывает согласование, аутентификацию и подобные задачи, как будто это был резидентный ядром драйвер. На стороне пространства пользователя это включает связь с приложением (или другая программа) через ее экспортируемые программируемые интерфейсы. На стороне ядра это включает связь с соответствующей семьей I/O Kit через кусок, создаваемый объектом драйвера той семьи. С точки зрения ядра интерфейс устройства, кажется, драйвер и известен как “пользовательский клиент”. С точки зрения приложения интерфейс устройства появляется как ряд функций, которые это может вызвать и через который это может передать данные ядру и получить данные назад от него. Поэтому, на элементном уровне, интерфейс устройства является указателем на таблицу указателей функции (несмотря на то, что он может также включать поля данных). Приложения, как только они получают экземпляр интерфейса устройства, могут вызвать любую из функций интерфейса.
Рисунок 2-4 иллюстрирует архитектуру интерфейса устройства, показывая приложение, получившее доступ к жесткому диску SCSI через интерфейс устройства. Лучше просматривать эту схему как изменение рисунка 2-2, показывающего ряд соединений объектов драйвера, сделанных для резидентного ядром драйвера диска SCSI.
В запуске тот же ряд действий — обнаружения устройств, создания куска, соответствия, загрузки драйвера — происходит от драйвера шины PCI до куска устройства SCSI. Но тогда кусок устройства SCSI соответствует и загружает интерфейс устройства как свой драйвер вместо резидентного ядром драйвера.
Прежде чем приложение может использовать интерфейсный устройством механизм для доступа к устройству, это должно найти устройство. Это выполняет это посредством соответствия вызываемого устройства процесса. В соответствии устройства приложение создает “соответствующий словарь”, указывающий свойства целевого устройства, затем вызывающий функцию Набора I/O, передающую в словаре. Функция ищет Реестр I/O и возвращается, один или несколько соответствующих драйверов возражают, что приложение может тогда использовать для загрузки надлежащего интерфейса устройства. Для больше по этой теме, посмотрите, что Соответствует Устройство
Если Вы разрабатываете пользовательский драйвер, который является не подкласс класса в семье I/O Kit, и Вы хотите, чтобы приложения были в состоянии получить доступ к драйверу, необходимо записать собственный интерфейс устройства. Любой код, связывающийся между пространством пользователя и ядром, должен использовать один или больше следующих средств:
Набор I/O использует прежде всего Маха общая память Маха и IPC. Напротив, сети и компоненты файловой системы OS X используют прежде всего системные вызовы BSD.
Файлы устройств POSIX
BSD, центральный компонент среды ядра OS X, экспортирует много программируемых интерфейсов, которые являются соответствующими стандарту POSIX. Эти интерфейсы включают связь с последовательным, хранением и сетевыми устройствами через файлы устройств. В любой основанной на UNIX системе, такой как BSD, файл устройств является специальным файлом, расположенным в /dev
это представляет блочное устройство или устройство посимвольного ввода-вывода, такое как терминал, дисковод или принтер. Если Вы знаете имя файла устройств (например, disk0s2
или mt0
) Ваше приложение может использовать функции POSIX такой как open
, read
, write
, и close
получить доступ и управлять связанным устройством.
Набор I/O динамично создает файлы устройств в /dev
поскольку это обнаруживает устройства. Следовательно, набор файлов устройств постоянно изменяется; различные устройства могли бы быть присоединены к файлам устройств в /dev
в любой момент, и те же устройства могли бы иметь различные имена файла устройств в разное время. Из-за этого Ваше приложение не может имена файлов твердого кодирующего устройства. Для определенного устройства необходимо получить из Набора I/O путь к его файлу устройств через процедуру, включающую соответствие устройства. Как только у Вас есть путь, можно использовать POSIX APIs для доступа к устройству.
Обратите внимание на то, что можно получить доступ к сетевым службам от пространства пользователя с помощью сокета BSD APIs. Однако необходимо обычно использовать сокеты, только если более высокий уровень, объединяющий APIS В СЕТЬ в средах Углерода и Какао, не предоставляет Вам функции, которых Вы требуете.