Класс Singleton в драйвере kext на основе IOKit

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

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

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

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

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

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

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

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

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

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

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


person Zohar81    schedule 24.05.2018    source источник


Ответы (1)


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

IOService как явный синглтон в любом случае сомнительна - вы уверены, что не должны использовать сопоставление 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
person pmdj    schedule 25.05.2018
comment
Действительно, есть ссылки на объекты IOKit, и я не возражаю против использования OSobject, но я хочу использовать его на протяжении всего проекта без передачи указателей ... возможно, вы можете объяснить свое предложение об использовании atomic pointers? Благодарность - person Zohar81; 27.05.2018
comment
@ Zohar81 Предполагая, что я правильно вас понимаю, и вы хотите иметь одноэлементный экземпляр класса, производного от OSObject, я обновил ответ примером. - person pmdj; 27.05.2018
comment
Спасибо, это именно то, что я хотел. Мне просто интересно, почему IOKit не допускает статических членов внутри объектов ... - person Zohar81; 28.05.2018
comment
@ Zohar81 Я думаю, это потому, что компилятор должен заблокировать конструктор. Вы пробовали использовать класс, отличный от iokit / osobject, с нетривиальным конструктором? - person pmdj; 28.05.2018