linux 工作队列(workqueue)——非常详细易懂

2024-02-05 08:58

本文主要是介绍linux 工作队列(workqueue)——非常详细易懂,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://blog.csdn.net/liuxd3000/article/details/7700247

在处理内核相关工作中, 我们经常看到工作队列(workqueue)的身影. 本文描述何为 linux workqueue.本文基于 2.6.32 的内核, 此时的工作队列还不是 cmwq.

为什么使用 workqueue?

在内核代码中, 经常希望延缓部分工作到将来某个时间执行, 这样做的原因很多, 比如

.在持有锁时做大量(或者说费时的)工作不合适.
.希望将工作聚集以获取批处理的性能.
.调用了一个可能导致睡眠的函数使得在此时执行新调度非常不合适.
...
内核中提供了许多机制来提供延迟执行, 使用最多则是 workqueue.

.如中断的下半部处理可延迟中断上下文中的部分工作;
.定时器可指定延迟一定时间后执行某工作;
.workqueue 则允许在进程上下文环境下延迟执行;
.内核中曾短暂出现过的慢工作机制 (slow work mechanism);
.异步函数调用(asynchronous function calls);
.各种私有实现的线程池;
...
术语

workqueue: 所有工作项(需要被执行的工作)被排列于该队列.
worker thread: 是一个用于执行 workqueue 中各个工作项的内核线程, 当 workqueue 中没有工作项时, 该线程将变为 idle 状态.
single threaded(ST): worker thread 的表现形式之一, 在系统范围内, 只有一个 worker thread 为 workqueue 服务.
multi threaded(MT): worker thread 的表现形式之一, 在多 CPU 系统上每个 CPU 上都有一个 worker thread 为 workqueue 服务.
使用步骤


创建 workqueue(如果使用内核默认的 workqueue, 此步骤略过).
创建工作项 work_struct.
向 workqueue 提交工作项.
工作项


数据结构(略有调整):


struct work_struct {
    atomic_long_t data;
    struct list_head entry;
    work_func_t func;
    struct lockdep_map lockdep_map;
};
struct delayed_work {
    struct work_struct work;
    struct timer_list timer;
};
静态地创建工作项:

DECLARE_WORK(n, f)
DECLARE_DELAYED_WORK(n, f)
动态地创建工作项:

INIT_WORK(struct work_struct work, work_func_t func); 
PREPARE_WORK(struct work_struct work, work_func_t func); 
INIT_DELAYED_WORK(struct delayed_work work, work_func_t func); 
PREPARE_DELAYED_WORK(struct delayed_work work, work_func_t func); 
内核默认的 workqueue

查阅源码可知, 内核默认的全局 workqueue 应为:

// 定义
static struct workqueue_struct *keventd_wq __read_mostly;


// 初始化
...
keventd_wq = create_workqueue("events"); // MT worker thread 模式.
...


// 确认对应的内核线程数目, 应等于 CPU 核数
$ lscpu
Architecture:          x86_64
CPU(s):                3
Thread(s) per core:    1
$ ps aux | grep "events"
root         9  0.0  0.0      0     0 ?        S    Feb09   1:15 [events/0]
root        10  0.0  0.0      0     0 ?        S    Feb09   0:59 [events/1]
root        11  0.0  0.0      0     0 ?        S    Feb09   0:59 [events/2]
工作项加入 keventd_wq 由下面两个函数之一完成:


int schedule_work(struct work_struct *work)
{
    return queue_work(keventd_wq, work);
}
int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
{
    return queue_delayed_work(keventd_wq, dwork, delay);
}
用户自定义的 workqueue

创建 workqueue:

create_singlethread_workqueue(name) // 仅对应一个内核线程
create_workqueue(name) // 对应多个内核线程, 同上文.
向 workqueue 中提交工作项:

int queue_work(workqueue_t *queue, work_t *work); 
int queue_delayed_work(workqueue_t *queue, work_t *work, unsigned long delay); 
取消 workqueue 中挂起的工作项以及释放 workqueue 此处略过.

工作队列的优点

使用简单.
执行在进程上下文, 从而可以睡眠, 被调度和抢占.
在多核环境下使用也非常友好.
example

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

static struct workqueue_struct *queue = NULL;
static struct work_struct work;

static void work_handler(struct work_struct *data)
{
    printk(KERN_ALERT "work handler for work_item in queue helloworkqueue\n");
    // workqueue 中的每个工作完成之后就被移除 workqueue.
    // 下面的语句会造成"死机", 原因可能是该 workqueue 占据了所有的 CPU 时间.
    // queue_work(queue, &work);
}

static int __init test_init(void)
{
    queue = create_singlethread_workqueue("helloworkqueue");
    if (!queue)
    {   
        goto err;
    }   
    INIT_WORK(&work, work_handler);
    queue_work(queue, &work);

    return 0;
err:
    return -1; 
}
static void __exit test_exit(void)
{
    destroy_workqueue(queue);
}

MODULE_LICENSE("GPL");
module_init(test_init);
module_exit(test_exit);
view rawworkqueue_example.cThis Gist brought to you by GitHub.
Makefile:

obj-m := wq.o
default:
    make -C /usr/src/linux-2.6.32.12-0.7 M=`pwd` modules


这篇关于linux 工作队列(workqueue)——非常详细易懂的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/680395

相关文章

Python设置Cookie永不超时的详细指南

《Python设置Cookie永不超时的详细指南》Cookie是一种存储在用户浏览器中的小型数据片段,用于记录用户的登录状态、偏好设置等信息,下面小编就来和大家详细讲讲Python如何设置Cookie... 目录一、Cookie的作用与重要性二、Cookie过期的原因三、实现Cookie永不超时的方法(一)

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

SpringBoot整合liteflow的详细过程

《SpringBoot整合liteflow的详细过程》:本文主要介绍SpringBoot整合liteflow的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...  liteflow 是什么? 能做什么?总之一句话:能帮你规范写代码逻辑 ,编排并解耦业务逻辑,代码

Linux中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机

在Linux终端中统计非二进制文件行数的实现方法

《在Linux终端中统计非二进制文件行数的实现方法》在Linux系统中,有时需要统计非二进制文件(如CSV、TXT文件)的行数,而不希望手动打开文件进行查看,例如,在处理大型日志文件、数据文件时,了解... 目录在linux终端中统计非二进制文件的行数技术背景实现步骤1. 使用wc命令2. 使用grep命令

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

SpringBoot集成LiteFlow工作流引擎的完整指南

《SpringBoot集成LiteFlow工作流引擎的完整指南》LiteFlow作为一款国产轻量级规则引擎/流程引擎,以其零学习成本、高可扩展性和极致性能成为微服务架构下的理想选择,本文将详细讲解Sp... 目录一、LiteFlow核心优势二、SpringBoot集成实战三、高级特性应用1. 异步并行执行2

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h