Автоматическая выгрузка драйвера OS X

Это мой первый вопрос здесь:)

В настоящее время я пишу общий kext, который предоставляет символьное устройство и предназначается для OSX 10.7+. Это чистый C, с нулевым IOKit/C++. (В случае, если это имеет значение, я тестирую драйвер 10.11.)

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

Согласно документации Apple для OSKextRetainKextWithLoadTag:

Когда автозагрузка включена, то вскоре после удаления последней ссылки kext он будет выгружен, если на него нет выдающихся ссылок и нет экземпляров его подклассов Libkern C++ (если таковые имеются).

...

Кекстам, которые определяют подклассы IOService, автоматически включается автозагрузка. Другие kexts могут использовать счетчик ссылок для управления автоматической выгрузкой без необходимости определять и создавать объекты Libkern C++.

Как уже упоминалось выше, мой kext не имеет каких-либо IOService подклассы (или любые классы, в этом отношении), поэтому я должен иметь возможность использовать OSKextRetainKextWithLoadTag,

Однако kext остается загруженным навсегда, после того как все файловые дескрипторы закрыты:

static int cdev_open(dev_t dev, int flags, int devtype, struct proc *p)
{
    /* ... */

    return OSKextRetainKextWithLoadTag(OSKextGetCurrentLoadTag()) == kOSReturnSuccess) ? 0 : kOSReturnError
}

static int cdev_close(dev_t dev, int flags, int devtype, struct proc *p)
{
    /* ... */

   OSKextReleaseKextWithLoadTag(OSKextGetCurrentLoadTag());
   return 0;
}

Кроме того, я написал "гибридную" версию своего kext, где я обернул процедуры запуска и остановки тонкой оболочкой C++, которая обеспечивает IOService подкласс (с IOResources в качестве провайдера), в случае, если выгрузка больше не поддерживается с общими кексами. Тот же результат.

(Я нашел несколько примеров общих кексов, которые используют OSKextRetainKextWithLoadTag а также OSKextReleaseKextWithLoadTag, но они очень старые и не знают, работают ли они с последними версиями OS X.)

Есть идеи, что я делаю не так?

Спасибо.

1 ответ

Рассмотрим следующее generic Kext:

kern_return_t xxxKext_start(kmod_info_t * ki, void *d)
{
    // this should set auto unload enabled 
    // and retain a refcount on the kext
    OSKextRetainKextWithLoadTag(OSKextGetCurrentLoadTag());

    // this should call OSKext::considerUnloads()
    // and remove the search retain and the previous call retain
    OSKextReleaseKextWithLoadTag(OSKextGetCurrentLoadTag());

    // somewhere here or even before - kext suppose to be unloaded automatically (according to Apple docs)
    return KERN_SUCCESS;
}

kern_return_t xxxKext_stop(kmod_info_t *ki, void *d)
{
   return KERN_SUCCESS;
}

Этот кекст должен автоматически исчезать через короткое время независимо от вызова kextunload или что-то подобное.

в 10.12.1 это работает отлично. Через некоторое время (не так быстро, как они описывают в своих документах), оно исчезнет из kextstat команда.

В 10.11.6 хотя по какой-то причине он останется загруженным.

Так что вы не делаете ничего плохого, в некоторых выпусках это просто ломается.

Другие вопросы по тегам