首页 > 解决方案 > 基于 IOKit 的 kext 驱动程序中的单例类

问题描述

我有一个类维护class IOSharedDataQueue : public IODataQueueIOKit 对象类型的实例。

该类与主类的各种方法解耦并调用,主类是基于 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 项目中使用,而无需传递指针。

标签: c++macoskerneliokitxnu

解决方案


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

推荐阅读