Управление удалением устройства

OS X является операционной системой, включающей замену в горячем режиме как функцию. Пользователи могут включить и демонтировать внешние устройства (например, диски массового хранения, диски CD-RW, модемы и сканеры), и система сразу делает то, что необходимо, чтобы сделать устройство применимым или, в случае удаления, зарегистрировать отсутствие устройства. Никакой системный перезапуск или завершение работы не необходимы.

В этой главе описываются, как Ваш драйвер должен реагировать на демонтаж своего устройства.

Фазы удаления устройства

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

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

Набор I/O выполняет организованное разрушение штабеля драйвера после удаления устройства в трех фазах. Первая фаза делает объекты драйвера в штабеле неактивными, таким образом, они не получают новых запросов I/O. Вторая фаза убирает ожидание и происходящие запросы I/O от очередей драйвера. Наконец, в третьей фазе, Набор I/O вызывает надлежащие методы жизненного цикла драйвера на драйверы, чтобы очистить выделенные ресурсы и отсоединить объекты из Реестра I/O прежде, чем освободить их. Рисунок 10-1 суммирует то, что происходит во время этих трех фаз, включая направление вызова в штабеле драйвера.

  Фазы рисунка 10-1 удаления устройства
Phases of device removal

Создание неактивных драйверов

Так же, как драйвер контроллера шины сканирует свою шину для обнаружения недавно вставленного устройства, он также обнаруживает просто демонтированные устройства. Когда это происходит, это вызывает terminate на его клиентском куске; terminate метод имеет поведение по умолчанию создания вызванного объекта, неактивного сразу. terminate метод также рекурсивно вызывается на клиенты; это вызывают на каждом объекте в штабеле выше контроллера шины, пока все объекты в штабеле не сделаны неактивными.

В результате того, чтобы быть сделанным неактивным, каждый объект также отправляет свои клиенты (или, в редких случаях, провайдерах) a kIOServicesIsTerminated сообщение через message метод. Когда terminate вызовите возвраты к исходной вызывающей стороне (драйвер контроллера шины), все объекты в штабеле неактивны, но штабель все еще присоединен к Реестру I/O.

Набор I/O предполагает, что возражает, что имеют многократных провайдеров (драйверы устройств RAID, например) не хотят быть разъединенным, и таким образом не вызывает terminate на них. Если эти объекты действительно хотят получить terminate сообщение, они должны реализовать requestTerminate метод для возврата true.

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

Очистка Очередей I/O

Сам Набор I/O координирует вторую фазу процедуры удаления устройства. Это запускается с недавно неактивного клиента драйвера контроллера шины и, как в первой фазе, повышает штабель драйвера, пока это не достигает листовых объектов. Это вызывает willTerminate метод на каждом объекте это встречается. Драйверы должны реализовать willTerminate метод для убирания любых очередей I/O запрашивает, чтобы они имели. Чтобы сделать это, они должны возвратить надлежащую ошибку запрашивающей стороне для каждого запроса в очереди.

После willTerminate был вызван на каждом объекте, Набор I/O тогда изменяет направление, идущее от листового объекта (или объектов) к корневому объекту штабеля драйвера, вызывая didTerminate на каждом объекте. Определенные объекты наверху штабеля — особенно пользовательские клиенты — могут решить провести подсчет запросов I/O, они выпустили и не получили ответ для (запросы I/O «в полете»). (Для обеспечения законности этого количества объект должен постепенно увеличить и постепенно уменьшить количество в контексте цикла работы.) Этим механизмом отслеживания, они могут определить, не был ли завершен какой-либо запрос I/O. Если это верно, они могут реализовать didTerminate возвратить ответ отсрочки true, таким образом, задерживая завершение, пока заключительный запрос I/O не завершается. В этой точке они могут сигнализировать, что завершение должно продолжиться путем вызова didTerminate на себе и возврате ответа отсрочки false.

Если драйвер присоединяет к клиентскому куску и имеет его открытый, Набор I/O принимает задержанный ответ (true) к didTerminate. Завершение продолжает быть задержанным, пока клиентский драйвер не закрывает своего провайдера.

В конце этой второй фазы не должно быть никаких поставленных в очередь запросов I/O или “в рейсе”. Набор I/O завершает эту фазу процедуры удаления устройства на ее собственном отдельном потоке и выполняет все вызовы клиентам на контексте цикла работы провайдера.

Отсоединение и выпуск объектов

В третьей фазе процедуры для удаления устройства Набор I/O вызывает методы жизненного цикла драйвера stop и detach (в том порядке) в каждом драйвере возражают в штабеле, который будет разъединен, запускающийся с листового объекта (или объектов). Драйвер должен реализовать stop функционируйте, чтобы закрыть, выпустить, или свободный любые ресурсы это открыло или создало в start функция, и оставить аппаратные средства в состоянии драйвером первоначально нашла его. Драйвер может реализовать detach удалить себя от его куска до его записи в Реестре I/O; однако, это поведение является значением по умолчанию, таким образом, драйвер обычно не должен переопределять detach. detach метод обычно сразу приводит к освобождению от объекта драйвера, потому что Реестр I/O обычно имеет финал retain на объекте.

Набор I/O завершает эту фазу процедуры удаления устройства на ее собственном отдельном потоке и выполняет все вызовы клиентам на контексте цикла работы провайдера.