[linux内核]linux中断下半部分——工作队列

一:工作队列概念

工作队列可以把工作推后,交由一个内核线程去执行,工作队列运行在进程上下文中,工作队列运行重新调度甚至睡眠内核驱动程序一般将下半部分交给内核缺省的工作者线程去做

二:驱动中使用工作队列的步骤

1,声明一个work_struct结构体

[cpp] view plaincopy

  1. struct work_struct work;

2,动态创建一个由work指向的工作,处理函数为func

[cpp] view plaincopy

  1. INIT_WORK(struct work_struct *work,void(*func)(void*),void*data)
  2. 例:INIT_WORK(&work,android_work);
  3. static void android_work(struct work_struct *data)

注:android_work()函数由一个内核线程调用,运行在进程上下文中,但是不能运行访问用户空间
3,对工作调度
工作调度就是将工作处理函数交给缺省的events工作线程

[cpp] view plaincopy

  1. schedule_work(&work);

三:工作队列的原理
与工作队列相关的数据结构是 struct workqueue_struct,系统默认的工作队列名称是:keventd_wq,默认的工作者线程叫:events/n,这里的n是处理器的编号,每个处理器对应一个线程。比如,单处理器的系统只有events/0这样一个线程。而双处理器的系统就会多一个events/1线程。默认工作队列keventd_wq和工作者线程events/n的建立在文件Kernel/kernel/workqueue.c中实现

四:创建自己的工作队列

[cpp] view plaincopy

  1. struct workqueue_struct *create_workqueue(cost char* name)

用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。输入参数

[cpp] view plaincopy

  1. create_singlethread_workqueue()只创建一个工作队列
  2. int queue_work(struct workqueue_struct*wq,struct work_struct *work)

五:补充

书上写的工作队列的实现是创建一个单独的线程来执行相应的work. 但是最新的内核实现却不是这样的,原先的工作队列的接口都快要废弃了,

New API:

[cpp] view plaincopy

  1. alloc_workqueue(name, flags, max_active)
  2. alloc_ordered_workqueue(const char *name, unsigned int flags)
  3. {
  4. return alloc_workqueue(name, WQ_UNBOUND | flags, 1);
  5. }

当向一个工作队列提交一个工作时,它并不是在指定的线程里运行,系统会维护一个Worker Pool, 每个Worker跑在一个单独的线程里,每一个CPU都有一个Worker Pool. 当有work需要处理时,就唤醒一个Worker,这样就减少了系统资源的占用(原先的实现是每创建一个工作队列,系统就创建一个线程,由于每个线程都需要有task_struct, pid等资源, 这样当系统中工作队列一多的话,资源占用率就很高了). 由于内核空间是所有进程共享的一块地址空间,因此在不同进程向工作队列提交的工作时,用户其实不用关心我这个工作到底是在哪个进程中处理的,但是这样的话,如果两个工作需要同步的话(比如访问一个共享的资源时),就得仔细考虑了,两个工作向同一个工作队列提交时,可能会被同时执行(分别跑在不同的CPU上), 这样RACE就产生了, 为了解决这个问题, 引入了WQ_UNBOUND标志 和 max_acitve = 1, 这两个参数指明了向这个工作队列提交一个工作时,这个工作不会绑定在特定的CPU上(如果没有指明WQ_UNBOUND 标志的话,在哪个CPU上提交的工作一定会在那个CPU上执行), max_active指明了这个工作队列后台有多少个worker线程与之绑定,默认参数为0,让系统来指定后台线程数。

时间: 2024-09-30 15:00:48

[linux内核]linux中断下半部分——工作队列的相关文章

Linux内核实现中断和中断处理(二)

上回说了Linux内核实现中断会把中断分为两部分进行处理,上回讲了上部分,这回讲下部分的设计思路 下半部的实现机制 软中断 tasklet:是通过软中断实现的,但和软中断有所不同 工作队列 讲上面几个实现机制之前先讲一个古老的方法,现在版本的内核虽然已经不再食用了,但是思想还在继续使用 最早的Linux只提供了“bottom half”这种机制实现下半部分,被称为BH,实现简单粗暴,设置一个全局变量(32位整数),表示一个32个节点的链表队列,哪位设置为1证明哪个bottom half就可以执行

再思linux内核在中断路径内不能睡眠/调度的原因(2010)【转】

转自:http://blog.csdn.net/maray/article/details/5770889 Linux内核中断路径中不能睡眠,为什么? 这里就行了很深入的讨论,值得一看:http://bbs2.chinaunix.net/viewthread.php?tid=1618430 但是,他们的讨论最后没有得出一个明确的结论.其中,cskyrain在8楼 的思考触及到了一个要点,但是没有深入展开: [c-sharp] view plain copy 1楼 发表于 2009-11-24 2

《深入理解Linux内核》软中断/tasklet/工作队列

软中断.tasklet和工作队列并不是Linux内核中一直存在的机制,而是由更早版本的内核中的"下半部"(bottom half)演变而来.下半部的机制实际上包括五种,但2.6版本的内核中,下半部和任务队列的函数都消失了,只剩下了前三者.本文重点在于介绍这三者之间的关系.(函数细节将不会在本文中出现,可以参考文献,点这里) (1)上半部和下半部的区别上半部指的是中断处理程序,下半部则指的是一些虽然与中断有相关性但是可以延后执行的任务.举个例子:在网络传输中,网卡接收到数据包这个事件不一

深入理解Linux内核-中断和异常

Linux内核代码查看 http://androidxref.com/ 中断:被定义位一个事件,它能改变处理器执行指令的顺序.它对应硬件(CPU.其他硬件设备)电路产生的电信号. 同步中断:指令执行时CPU控制单元产生:称为同步,是因为只有在一条指令终止执行后CPU才回发出中断.也被称为异常 异步中断:其他硬件设备按照CPU时钟信号随机产生的.也被简称中断 中断的约束:1.中断必须尽快处理完成:中断一般被分两部分执行:关键而且紧急的部分,内核立即执行:其余部分内核稍后执行: 2.中断的处理必须能

[linux内核][linux]linux内核时间管理基础

一,linux时间管理基础http://blog.csdn.net/droidphone/article/details/7975694http://blog.csdn.net/smilingjames/article/details/6205540linux所有时间基础都是以低层硬件为基础的,低层硬件有GPT和cpu local timer,比如GPT的时钟源为13M HZlinux低层时间的架构分为clock source,clock event device,clock source上层分

[linux内核]linux内核编程规范

1,__attrubte__关键字的作用 点击打开链接 __attrubte__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐.struct str_struct{        __u8    a;        __u8    b;        __u8    c;        __u16   d;} __attribute__ ((packed));以上结构体的大小为5/*  当用到typedef时,要特别注意__attribut

[linux内核][LINUX内核编程]学习笔记(二)

linux内核————队列 linux内核——队列 定义: [cpp] view plaincopy struct __kfifo{ unsigned int in;  //入队偏移,写索引 unsigned int out;  //出队偏移,读索引 unsigned int mask; unsigned int esize; void *data; } 使用: 创建一个队列,该函数创建并初始化一个大小为size的kfifo: [cpp] view plaincopy 38 int __kfif

linux 内核 linux kernel travel

linux 内核 kernel_核 travel_旅行 linux kernel travel linux 2.6 1 hellomod.c 001 // hello world driver for linux 2.6 #include <linux/module.h>                  /*所有模块都要使用头文件module.h*/ #include<linux/kernel.h>               /*kernel.h包含了常用的内核函数*/ #in

[linux内核][linux中断]——软中断机制

点击打开链接 一,linux软中断的概念软中断(softirq)常常表示可延迟函数的所有种类,目前linux上使用的软中断个数是有限的,linux最多注册32个,目前使用了10个,在interrupt.h中定义,中断上下文:表示内核当前正在执行一个中断处理程序或者一个可延迟函数.软中断(即使同一类型的软中断)可以并发运行在多个CPU上,因此软中断是可重入函数必须使用自旋锁保护其数据结构.一个软中断不会去抢占另外一个软中断. 软中断和tasklet的区别由于软中断必须使用可重入函数,这就导致设计上