Linux kernel 在内核模块中定期隐藏硬件原始请求,如何?

Linux kernel 在内核模块中定期隐藏硬件原始请求,如何?,linux-kernel,scheduling,atomic,Linux Kernel,Scheduling,Atomic,我正在编写一个内核模块,需要定期询问hid原始设备。 我尝试了hrtimer和一个简单的计时器,每次调用hid_hw_raw_请求时,我都会遇到一个BUG:原子时调度 如果我在计时器函数之外尝试相同的函数,例如在init中,它可以正常工作,没有bug 如何定期调用此函数而不产生任何错误?您需要使用工作队列来发出hid\u hw\u raw\u请求作为延迟工作。这可以在以下示例模块中完成: #include <linux/kernel.h> #include <linux/mod

我正在编写一个内核模块,需要定期询问hid原始设备。 我尝试了hrtimer和一个简单的计时器,每次调用hid_hw_raw_请求时,我都会遇到一个BUG:原子时调度

如果我在计时器函数之外尝试相同的函数,例如在init中,它可以正常工作,没有bug


如何定期调用此函数而不产生任何错误?

您需要使用工作队列来发出hid\u hw\u raw\u请求作为延迟工作。这可以在以下示例模块中完成:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>

static void hid_work_handler(struct work_struct *hid_work);

static struct workqueue_struct *hid_workqueue;
static DECLARE_WORK(hid_work, hid_work_handler);

static void hid_work_handler(struct work_struct *hid_work)
{
        ...
        hid_hw_raw_request(...);
        ...
}

static int __init hid_work_init(void)
{
        if (!hid_workqueue)
                hid_workqueue = create_singlethread_workqueue("hid_workqueue");

        if (hid_workqueue)
                queue_work(hid_workqueue, &hid_work);

        return 0;
}

static void __exit hid_work_exit(void)
{
        if (hid_workqueue) {
                flush_workqueue(hid_workqueue);
                destroy_workqueue(hid_workqueue);
        }
}

module_init(hid_work_init);
module_exit(hid_work_exit);

MODULE_DESCRIPTION("hid_work_test");
MODULE_LICENSE("GPL");

请注意,对于真正的实现,您需要创建自己的数据结构,其中包含要排队的结构work\u struct。此数据结构可能包含hiddev、缓冲区等,hid_work_处理程序需要这些数据结构来执行实际传输。有关更多详细信息,请参见LDD3第7章,尽管调用的语法已经过时,但基本解释仍然适用

您需要使用工作队列将hid_hw_raw_请求作为延迟工作发出。这可以在以下示例模块中完成:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>

static void hid_work_handler(struct work_struct *hid_work);

static struct workqueue_struct *hid_workqueue;
static DECLARE_WORK(hid_work, hid_work_handler);

static void hid_work_handler(struct work_struct *hid_work)
{
        ...
        hid_hw_raw_request(...);
        ...
}

static int __init hid_work_init(void)
{
        if (!hid_workqueue)
                hid_workqueue = create_singlethread_workqueue("hid_workqueue");

        if (hid_workqueue)
                queue_work(hid_workqueue, &hid_work);

        return 0;
}

static void __exit hid_work_exit(void)
{
        if (hid_workqueue) {
                flush_workqueue(hid_workqueue);
                destroy_workqueue(hid_workqueue);
        }
}

module_init(hid_work_init);
module_exit(hid_work_exit);

MODULE_DESCRIPTION("hid_work_test");
MODULE_LICENSE("GPL");

请注意,对于真正的实现,您需要创建自己的数据结构,其中包含要排队的结构work\u struct。此数据结构可能包含hiddev、缓冲区等,hid_work_处理程序需要这些数据结构来执行实际传输。有关更多详细信息,请参见LDD3第7章,尽管调用的语法已经过时,但基本解释仍然适用

您好,非常感谢您详细的回答!我会尽快尝试,但它看起来正是我所寻找的!您好,非常感谢您详细的回答!我会尽快尝试,但它看起来正是我所寻找的!