zoukankan      html  css  js  c++  java
  • Linux 内核工作队列之work_struct 学习总结

    前言

    编写Linux驱动的时候对于work_struct的使用还是很普遍的,很早之前就在阅读驱动源码的时候就看到了它的踪影,根据其命名大概知道了它的具体作用,但是仍然不知所以,同时,伴随出现的还有delayed_work以及workqueue_struct,抱着知其然并知其所以然的态度,在这里归纳总结一下work_struct,以及如何在驱动中使用,因为工作队列相对来说比较复杂,篇幅和能力有限,只能介绍相对重要的部分。

    workqueue

    内核里一直运行类似worker thread,它会对工作队列中的work进行处理,大致的工作流程原理可以参考下图所示;

    在这里插入图片描述

    在这里的work则是work_struct变量,并且绑定一个执行函数——typedef void (*work_func_t)(struct work_struct *work);。在worker thread中会对非空的工作队列进行工作队列的出队操作,并运行work绑定的函数。

    work_struct

    work_struct的数据结构如下,暂时我们还无法关注其原理,只关注如何去开启一个work

    #include <linux/include/workqueue.h>
    
    typedef void (*work_func_t)(struct work_struct *work);
    
    struct work_struct {
    	atomic_long_t data;
    	struct list_head entry;
    	work_func_t func;
    #ifdef CONFIG_LOCKDEP
    	struct lockdep_map lockdep_map;
    #endif
    };
    

    通过数据结构可以知道,每当我们定义一个work_struct变量的时候,需要绑定一个work_func_t类型的函数指针。

    函数 功能
    INIT_WORK(_work, _func) 初始化一个work
    INIT_WORK_ONSTACK(_work, _func) 在栈上初始化一个work
    flush_work(struct work_struct *work); 销毁一个work
    schedule_work(struct work_struct *work) 调度一个work开始运行

    例程

    下面写了 一个demo,模块初始化之后会每隔5秒调度work开始运行,最终demo_work_func会运行规定的次数,并打印传递的参数和进程信息。

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/time.h>
    
    #include <linux/jiffies.h>
    #include <linux/workqueue.h>
    #include <linux/slab.h> //kmalloc kfree
    
    #include <linux/sched.h>
    #include <linux/delay.h>
    
    static char data[] = "test for demo work";
    
    struct work_ctx{
    	struct work_struct real_work;
    	char *str;
    	int arg;
    }work_ctx;
    
    struct work_ctx *demo_work;
    
    static void demo_work_func(struct work_struct *work){
    
    	struct work_ctx *temp_work = container_of(work,struct work_ctx,real_work);
    	printk(KERN_INFO "[work]=> PID: %d; NAME: %s
    ", current->pid, current->comm);
    	printk(KERN_INFO "[work]=> sleep 1 seconds
    ");
    	set_current_state(TASK_INTERRUPTIBLE);
    	schedule_timeout(1 * HZ); //Wait 1 seconds
    	printk(KERN_INFO "[work]=> data is: %d  %s
    ", temp_work->arg,temp_work->str);
    }
    
    static int __init demo_thread_init(void){
    	int count = 10;
    	demo_work = kmalloc(sizeof(*demo_work),GFP_KERNEL);	
    	INIT_WORK(&demo_work->real_work, demo_work_func);
    	demo_work->str = data;
    	while(count--){
    		msleep(5000);
    		demo_work->arg = count;
    		schedule_work(&demo_work->real_work);
    
    	}
    	return 0;
    }
    
    module_init(demo_thread_init);
    
    static void __exit demo_thread_exit(void){
    	flush_work(&demo_work->real_work);
    	kfree(demo_work);
    }
    module_exit(demo_thread_exit);
    
    MODULE_LICENSE("GPL");	
    

    运行结果

    [    8.500146] [work]=> PID: 37; NAME: kworker/0:1
    [    8.500216] [work]=> sleep 1 seconds
    [    9.499783] [work]=> data is: 9  test for demo work
    [   13.503165] [work]=> PID: 37; NAME: kworker/0:1
    [   13.503213] [work]=> sleep 1 seconds
    [   14.503122] [work]=> data is: 8  test for demo work
    [   18.506493] [work]=> PID: 37; NAME: kworker/0:1
    [   18.506534] [work]=> sleep 1 seconds
    [   19.506460] [work]=> data is: 7  test for demo work
    [   23.509833] [work]=> PID: 37; NAME: kworker/0:1
    [   23.509874] [work]=> sleep 1 seconds
    [   24.510060] [work]=> data is: 6  test for demo work
    [   28.513161] [work]=> PID: 37; NAME: kworker/0:1
    [   28.513206] [work]=> sleep 1 seconds
    [   29.513121] [work]=> data is: 5  test for demo work
    [   33.516502] [work]=> PID: 37; NAME: kworker/0:1
    [   33.516545] [work]=> sleep 1 seconds
    [   34.516452] [work]=> data is: 4  test for demo work
    [   38.519819] [work]=> PID: 37; NAME: kworker/0:1
    [   38.519860] [work]=> sleep 1 seconds
    [   39.519782] [work]=> data is: 3  test for demo work
    [   43.523151] [work]=> PID: 37; NAME: kworker/0:1
    [   43.523191] [work]=> sleep 1 seconds
    [   44.523117] [work]=> data is: 2  test for demo work
    [   48.526495] [work]=> PID: 37; NAME: kworker/0:1
    [   48.526542] [work]=> sleep 1 seconds
    [   49.526444] [work]=> data is: 1  test for demo work
    [   53.539699] [work]=> PID: 37; NAME: kworker/0:1
    [   53.539763] [work]=> sleep 1 seconds
    [   54.542925] [work]=> data is: 0  test for demo work
    

    参考

    https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s08.html

    https://kukuruku.co/post/multitasking-in-the-linux-kernel-workqueues/

  • 相关阅读:
    trackr: An AngularJS app with a Java 8 backend – Part III
    trackr: An AngularJS app with a Java 8 backend – Part II
    21. Wireless tools (无线工具 5个)
    20. Web proxies (网页代理 4个)
    19. Rootkit detectors (隐形工具包检测器 5个)
    18. Fuzzers (模糊测试器 4个)
    16. Antimalware (反病毒 3个)
    17. Debuggers (调试器 5个)
    15. Password auditing (密码审核 12个)
    14. Encryption tools (加密工具 8个)
  • 原文地址:https://www.cnblogs.com/unclemac/p/12783404.html
Copyright © 2011-2022 走看看