【问题标题】:Singleton class in IOKit based kext driver基于 IOKit 的 kext 驱动程序中的单例类
【发布时间】:2018-05-24 11:21:18
【问题描述】:

我有一个类,它维护来自类型 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 项目中使用,而无需传递指针。

【问题讨论】:

    标签: c++ macos kernel iokit xnu


    【解决方案1】:

    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
    

    【讨论】:

    • 确实引用了 IOKit 对象,我不介意从 OSobject 派生,但我希望在整个项目中使用它而不传递指针......也许你可以解释你关于使用 @987654325 的建议@?谢谢
    • @Zohar81 假设我对您的理解正确,并且您想要一个 OSObject 派生类的单例实例,我已经用一个示例更新了答案。
    • 谢谢,这正是我想要的。我只是想知道为什么 IOKit 不允许对象内的静态成员...
    • @Zohar81 我认为这是因为编译器必须在构造函数周围加锁。您是否尝试过使用非平凡构造函数的非 iokit/osobject 类?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多