基于IOKit的kext驱动程序中的Singleton类

时间:2018-05-24 11:21:19

标签: c++ macos kernel iokit xnu

我有一个类来维护类型class IOSharedDataQueue : public IODataQueue的实例,它是IOKit对象。

该类是从主类的各种方法中解耦并调用的,这是基于IOKit的类(派生自IOService)。

在尝试将此类转换为单例时,我已使用以下实现添加了getInstance函数:

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

然而,似乎c ++ 11初始化singleton的方式应该在IOKit编译器中工作,并且Xcode产生以下错误:

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

问题是,它适用于不包含基于IOKIt的对象的类。

也许有人遇到过这个问题,我还没有看到任何有关此限制的文档。

编辑:

我发现如果我的类不以任何方式包含任何IOResources对象,它可以设计为带有guard变量的单例。

但是,我仍然希望能够创建一些简单且包含的包装器,以便在我的IOKit项目中使用而不传递指针。

1 个答案:

答案 0 :(得分:2)

IOKit对象是引用计数的,必须始终使用new进行实例化,并通过调用release()来销毁。因此,无论线程安全的静态初始化器在kexts中是否可用,您都不应该静态分配IOKit对象。您可以使用原子指针或基于锁的机制在第一次调用函数时实例化对象,或者在固定时间创建实例。

作为显式单例的IOService无论如何都是可疑的 - 你确定你不应该使用基于IOResource的IOKit匹配来创建单个实例吗?

我建议的内容如下:

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