Автоматическая выгрузка драйвера 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.)

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

Спасибо.

3

Решение

Рассмотрим следующее 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 хотя по какой-то причине он останется загруженным.

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

1

Другие решения

Других решений пока нет …