Класс Singleton в драйвере kext на основе IOKit - PullRequest
0 голосов
/ 24 мая 2018

У меня есть класс, который поддерживает экземпляр типа class IOSharedDataQueue : public IODataQueue, который является объектом IOKit.

Класс отделен и вызывается из различных методов основного класса, который является классом на основе IOKit (производным от IOService).

При попытке преобразовать этот класс в синглтон, я 'Мы добавили функцию getInstance со следующей реализацией:

myclass& myclass::getInstance()
{
    static myclass instance;
    return instance;
}

Однако, похоже, что способ инициализации синглтона c ++ 11 должен работать в компиляторе IOKit, и Xcode выдает следующую ошибку:

This initialization requires a guard variable, which the kernel does not support

Дело в том, что он работает для классов, которые не содержат объектов на основе IOKIt.

Возможно, кто-нибудь сталкивался с этой проблемой, я не видел документации об этом ограничении.

РЕДАКТИРОВАТЬ:

Я обнаружил, что если мой класс не содержит какого-либо объекта IOResources, он может быть спроектирован как синглтон с переменной защиты.

Тем не менее, я все еще хочу иметь возможность создавать несколько простых и закрытых оболочек, которые будут использоваться в моем проекте IOKit без передачи указателей.

1 Ответ

0 голосов
/ 25 мая 2018

Объекты IOKit подсчитываются по ссылке, и их всегда нужно создавать с new и уничтожать, вызывая release().Поэтому, несмотря на тот факт, что поточно-ориентированные статические инициализаторы недоступны в кексах, вам все равно не следует статически размещать объекты IOKit.Вы можете использовать атомарный указатель или механизм на основе блокировки для создания экземпляра вашего объекта при первом вызове функции или создать экземпляр в фиксированное время.Вы уверены, что не следует использовать IOKit на основе IOResource для создания единственного экземпляра?

Я предлагаю что-то вроде:

static myclass* singleton_instance;
myclass* myclass::getInstance()
{
    if (singleton_instance == nullptr)
    {
        myclass* new_instance = new myclass();
        new_instance->init();
        if (!OSCompareAndSwapPtr(nullptr, new_instance, &singleton_instance))
        {
            new_instance->release();
        }
    }
    return singleton_instance;
}
// TODO: release singleton_instance when kext unloads
...