【linux内核】workqueue_struct工作队列

配置笔记本电脑安装centos7关闭盖子不休眠

struct workqueue_struct *my_wq;
my_wq = alloc_workqueue("my_wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
INIT_WORK(&my_work, my_work_func);
queue_work(my_wq, &my_work);
  • 调用 alloc_workqueue():仅创建队列对象;
  • 调用 queue_work():发现没有 worker,创建一个;
  • 线程启动,执行 my_work_func();
  • 执行完后线程保持空闲,等待下一个任务。

在/etc/systemd/logind.conf文件中添加一行配置:

HandleLidSwitch=ignore

一个 struct work_struct 在任意时刻,只能处于:未排队 / 正在执行 / 已排队 之一。同一个 work_struct, 如果已经在队列里或正在执行,再 queue_work(),返回 false,不会再次入队,但这条规则只针对“同一个 work_struct 实例”。

场景分析:一个结构体里定义了 两个 struct work_struct,分别执行不同的函数,投递到 同一个 workqueue_struct:

struct foo {
    struct work_struct work_a;
    struct work_struct work_b;
};

✅ 情况 A:work_a 在队列中,work_b 入队。是完全没问题的。work_a 和 work_b 是两个独立的 work。即使:work_a 还在队列里 / 正在跑。work_b 也可以成功 queue_work()。最终行为:按 workqueue 的调度顺序执行,串行 or 并行取决于你用的 queue 类型,不会导致第二个执行不了。

 

情况 B:重复 queue 同一个 work(容易踩坑):

queue_work(wq, &foo->work_a);
queue_work(wq, &foo->work_a);   // ❌

第二次queue_work() 返回 false,不会再次执行但:不会取消第一次只是“合并请求”这点经常被误判成 “work 丢了”

 

两个 work 共用了同一个 work_struct:

struct foo {
    struct work_struct work;
};

然后想复用:

INIT_WORK(&foo->work, fn_a);
queue_work(wq, &foo->work);

INIT_WORK(&foo->work, fn_b);  // 💥 危险
queue_work(wq, &foo->work);

这是未定义行为,非常容易:第二个根本不执行,甚至直接炸。

 

推荐的设计模式:

两个不同逻辑 → 两个 work_struct(推荐)

struct foo {
    struct work_struct worka;
    struct work_struct workb;
};

INIT_WORK(&foo->worka, fn_a);
INIT_WORK(&foo->workb, fn_b);

queue_work(wq, &foo->worka);
queue_work(wq, &foo->workb);

参考资料

1. workqueue_struct工作队列

2. workqueue(linux kernel 工作队列)

posted @ 2025-09-10 19:27  苏格拉底的落泪  阅读(44)  评论(0)    收藏  举报