linux内核源码分析中断work_queue

目录

一、工作队列

二、工作队列结构体

三、工作队列初始化(系统自带)

缺省工作队列示例

四、自定义工作队列

自定义示例


一、工作队列

工作队列可以把工作推后,交由一个内核线程去执行,工作队列允许重新调度甚至是睡眠。

内核把推迟的任务交给特定的通用线程的这样一种接口

用途:中断处理、进程同步、定时等场合。可以使用等待队列实现阻塞进程的唤醒。它以队列为基础数据结构,与进程调度机制紧密结合,能够用于实现内核中的异步时间通知机制,同步对系统资源的访问等待

二、工作队列结构体

1、正常工作结构体

struct work_struct {
	atomic_long_t data;
	struct list_head entry;
	work_func_t func;
...
};

2、延迟工作结构体

queue_delayed_work用于向工作队列提交delayed_work实例,它确保在延期工作执行之前,少会经过由delay指定的一段时间。

struct delayed_work {
    struct work_struct work;
    struct timer_list timer; //定时器,用于实现延迟
};

3、工作队列

struct workqueue_struct {
	struct list_head	pwqs;		/* WR: all pwqs of this wq */
	struct list_head	list;		/* PR: list of all workqueues */

	struct mutex		mutex;		/* protects this wq */
	int			work_color;	/* WQ: current work color */
	int			flush_color;	/* WQ: current flush color */
	atomic_t		nr_pwqs_to_flush; /* flush in progress */

	struct list_head	maydays;	/* MD: pwqs requesting rescue */
	struct worker		*rescuer;	/* MD: rescue worker */

	int			nr_drainers;	/* WQ: drain in progress */
	int			saved_max_active; /* WQ: saved pwq max_active */

	struct workqueue_attrs	*unbound_attrs;	/* PW: only for unbound wqs */
	struct pool_workqueue	*dfl_pwq;	/* PW: only for unbound wqs */

	char			name[WQ_NAME_LEN]; /* I: workqueue name */
	struct rcu_head		rcu;

	/* hot fields used during command issue, aligned to cacheline */
	unsigned int		flags ____cacheline_aligned; /* WQ: WQ_* flags */
	struct pool_workqueue __percpu *cpu_pwqs; /* I: per-cpu pwqs */
	struct pool_workqueue __rcu *numa_pwq_tbl[]; /* PWR: unbound pwqs indexed by node */
};

三、工作队列初始化(系统自带)

缺省的工作者线程都会从多个地方得到后被推后的工作,交给缺省的工作线程去做。

系统默认的工作队列名:keventd_wq

默认的工作者线程:events/n,n代表处理器编号

例如:单处理器的系统只有events/0这样一个线程,而双处理器的系统就会多一个events/1线程。

缺省系统调用为

start_kernel->rest_init->do_basic_setup->init_workqueues

工作队列相关函数

//静态创建
DECLARE_WORK(name,fun)
//带延时,
DECLARE_DELAYED_WORK(name,fun)

//动态创建
INIT_WORK(_work, _func)
//带延时
INIT_DELAYED_WORK(_work, _func)

工作调度

int schedule_work(struct work_struct *work) 
//延迟调度
int schedule_delayed_work(struct delay_work *dwork, unsigned long delay)

刷新与取消

//刷新工作队列
void flush_scheduled_work(void)

//取消延迟工作
static inline int cancel_delayed_work(struct delayed_work *work)

缺省工作队列示例

每隔一秒进行一次调度,并将新的值传递到后执行队列中

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/socket.h>
#include <net/sock.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/workqueue.h>

#define BUF_SIZE 1024
struct task_struct *main_task;

struct my_work {
    struct work_struct w;
    int data;
};
static struct my_work real_work;

static inline void sleep(unsigned sec)
{
    __set_current_state(TASK_INTERRUPTIBLE);
    schedule_timeout(sec * HZ);
}

static void my_work_func(struct work_struct *work)
{
    struct my_work *pwork;
    pwork = container_of(work, struct my_work, w);

    printk(KERN_NOTICE "index %d\n", pwork->data);
}

static int queue_work_(void *data)
{
    int index = 0;
    INIT_WORK(&real_work.w, my_work_func);

    while (!kthread_should_stop()) {
        printk(KERN_NOTICE "server run %d\n", index);
        real_work.data = index;

        if (schedule_work(&real_work.w) == 0) {
            printk(KERN_NOTICE " work failed!\n");
        }
        index ++;
        sleep(1);
    }

    return 0;
}

static int model_init(void)
{
    printk("init, workqueue \n");
    //task_struct init
    main_task = kthread_run(queue_work_,NULL,"queue_work");

    return 0;
}
static void model_exit(void)
{
    printk("exit!\n");
    kthread_stop(main_task);

}

module_init(model_init);
module_exit(model_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyong");

 使用dmesg查看打印输出如下

[ 2369.599934] server run 0
[ 2369.599938] index 0
[ 2370.609331] server run 1
[ 2370.609335] index 1
[ 2371.632714] server run 2
[ 2371.632716] index 2
[ 2372.656413] server run 3
[ 2372.656415] index 3
[ 2373.680923] server run 4
[ 2373.680927] index 4
[ 2374.705357] server run 5
[ 2374.705362] index 5
[ 2375.729315] server run 6
[ 2375.729320] index 6
[ 2376.752834] server run 7
[ 2376.752838] index 7
[ 2377.777063] server run 8
[ 2377.777069] index 8
[ 2378.801040] server run 9
[ 2378.801042] index 9
[ 2379.827048] server run 10

四、自定义工作队列

函数含义与默认差不多

create_workqueue(name) 

int queue_work(struct workqueue_struct *wq, struct work_struct *work)

int queue_delayed_work(struct workqueue_struct *wq,struct delayed_work *dwork, unsigned long delay)

void flush_workqueue(struct workqueue_struct *wq)

void destroy_workqueue(struct workqueue_struct *wq)

自定义示例

实验现象:10秒钟后执行延迟函数,使用dmesg 查看输出信息

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

static struct workqueue_struct *wq;                 /*声明一个工作队列*/
static struct delayed_work d_work;                  /*声明一个延期工作实例*/

//工作队列延迟处理函数
void print_hello(struct work_struct *work)
{
    printk("print workqueue` ...\n");
}

static int __init wq_init(void)
{
    int ret = 0;

    wq = create_workqueue("test_wq"); //创建工作队列
    if (!wq) {
        printk("create workqueue failed \n");
        return -1; 
    }   


	INIT_DELAYED_WORK(&d_work, print_hello);//动态延迟初始化工作队列
    ret = queue_delayed_work(wq, &d_work, msecs_to_jiffies(10000));  //向工作队列添加工作项

    return 0;
}

static void __exit wq_exit(void)
{
    int ret = 0;

    printk("test_wy exit\n");
    ret = cancel_delayed_work(&d_work);             /*取消工作项*/
    flush_workqueue(wq);                            /*刷新工作队列*/
    destroy_workqueue(wq);                          /*销毁工作队列*/
}

module_init(wq_init);
module_exit(wq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyong");
MODULE_DESCRIPTION("workqueue driver");

Makefile文件 

ifneq ($(KERNELRELEASE),)
obj-m:=main.o
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
        $(MAKE) -C $(KERNELDIR)  M=$(PWD) modules
clean:
        rm -rf *.o *.mod.c *.mod.o *.ko
endif

参考:
《深入理解linux内核》
《Linux内核深度解析》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值