Linux内核中的中断
http://blog.csdn.net/weiqing1981127/article/details/8298585
中断处理程序是被内核调用来响应中断的,它运行在中断上下文,中断处理程序是上半部,当接收到一个中断,它就立即开始执行,但只做有严格时限的工 作,例如对接收的中断进行应答或复位硬件,这些工作都是在所有中断被禁止的情况下完成。能够被允许稍后完成的工作会推迟到下半部去。
中断处理程序的注册是通过request_irq函数,由于该函数内部有分配内存的操作,所以它不能在中断上下文或其他不允许阻塞的代码中调用。Linux中的中断处理程序是无须重入的,因为当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,而当前中断线总是被禁止的,由此可见,同一个中断处理程序绝不会被同时调用以处理嵌套的中断。中断处理程序不用关心中断栈和内核栈的设置,尽量节约内核栈空间就是了。
锁提供保护机制,防止来自其他处理器的并发访问,而禁止中断提供的保护机制则是防止来自其他中断处理程序的并发访问。禁止中断包括禁止当前处理器的所有中断和禁止一条中断线两种,禁止所有中断可以使用local_irq_save和local_irq_restore函数,禁止一个中断线可以使用disable_irq函数。
查看使用的中断号可以用cat /proc/interrupts得到。中断系统的状态可以通过几个函数获得,irqs_disabled函数查看本地中断传递是否被禁止;in_interrupt函数查看是否在中断上下文;in_irq查看是否是当前正在执行中断处理程序。
为什么要引入下半部呢?因为中断处理流程的上半部有一些局限:其一,中断以异步方式执行,它有可能打断其他重要代码,为了避免打断时间过长,中断处 理程序应该执行的快些。其二,如果当前有一个中断处理程序正在执行,需要做一个禁止其他中断的操作,禁止中断后硬件和操作系统无法通信了,所以也有中断处 理快点。其三,中断处理往往需要对硬件操作,所以也需要快点。其四,中断处理程序不在进程上下文,不能睡眠,这也限制了它们所做的事。
下半部的任务就是执行与中断处理密切相关中断处理程序本身不执行的工作。中断处理程序往往需要通过操作硬件对中断的到达进行确认,有时它还会从硬件 拷贝数据。我们将对时间非常敏感,与硬件相关,要保证不被其他中断打断的事情放在中断处理程序中执行,其他任务考虑放到下半部执行。下半部执行的关键在于 当它们运行的时候,运行相应所有的中断。
在2.6内核版本中,下半部实现的机制包括软中断、tasklet和工作队列。
软中断是一组静态定义的下半部接口,有32个,可以在所以处理器上同时执行,软中断必须在编译期间就进行静态注册,这里的软中断不是系统调用中提到的软中断。软中断在下面地方会被执行:其一,一个硬件中断代码处返回时。其二,在ksoftirqd内核线程中(每个处理器都有一组辅助处理软中断和tasklet的内核线程,当大量软中断出现时,内核会唤醒一组内核线程来处理这些负载,这个内核线程就是ksoftirqd线程)。其三,在那些显式检查和执行处待理的软件中断的代码中,如网络子系统。只有网络和SCSI子系统直接使用软中断,对于世界要求严格并能自己高效地完成加锁工作的应用,软中断是正确的选择。
tasklet有两种类软中断代表:HI_SOFTIRQ和TASKLET_SOFTIRQ,前者优先级更高。所有的tasklet都通过重复运用HI_SOFTIRQ和TASKLET_SOFTIRQ这两个软中断实现。当一个tasklet被调用时,内核就会唤醒这两个软中断中的一个,随后该软中断会被特定的函数处理,执行所有已调度的tasklet,这个函数保证同一时间里只有一个给定类别的tasklet会被执行。Tasklet不能睡眠,这意味着你不能在tasklet中使用信号量或其他什么阻塞式的函数,同时由于tasklet运行时允许响应中断,所以你必须做好预防(如屏蔽中断然后获得一个锁),另外,你可以调用tasklet_disable函数禁止某个指定的tasklet,你也可以使用tasklet_kill从挂起队列中去掉一个tasklet。
DECLARE_TASKLET(test_tasklet,test_tasklet_func,0); //定义
void test_tasklet_func(void) //处理函数
{
printk("tasklet is executing!\n");
}
tasklet_schedule(&test_tasklet); //调度
工作队列可以把工作推后,交给一个内核线程去执行,这个下半部分总是会在进程上下文中执行,工作队列运行重新调度甚至是睡眠,它是唯一能在进程上下 文中运行的下半部实现机制,也只有它可以睡眠。尽管操作处理函数运行在进程上下文,但它不能访问用户空间,因为内核线程在用户空间没有相关的内存映射,通 常只有发生系统调用时,内核才会代表用户空间的进行运行。
工作队列子系统提供了一个缺省的工作者线程,我们只要把需要推后执行的任务交给特定的通用线程就好了,缺省的工作者线程叫events/n,我们一般使用这个缺省的工作者线程,但是如果你需要在工作者线程中执行大量的处理操作,创建自己的工作者线程就更好了。系统的每个CPU都会有一个工作者线程,每个工作者线程都是由struct cpu_workqueue_struct结构体表示,而struct workqueue_struct则表示给定类型(即同类型)的所有工作者线程。
INIT_WORK(&button_dev->work, gpio_keys_report_event); //定义
static void gpio_keys_report_event(struct work_struct *work) //处理函数
{
key_values[0] = '0' ; //清除按键标识
input_report_key(channel, BTN_0, !!ev_press); //向input子系统报告按键事件
input_sync(channel); //同步操作
ev_press = 0; //清除按键值
}
schedule_work(&button_dev->work); //调度工作队列处理函数
cancel_work_sync(&button_dev->work); //删除工作队列
tasklet基于软件中断,而工作队列是靠内核线程实现的,如果你有休眠的需要,那么你使用工作队列,否则最好使用tasklet机制。为了保证共享数据,一般先得到一个锁,然后使用local_bh_disable函数禁止下半部,但local_bh_disable函数并不能禁止工作队列的执行,因为工作队列不涉及异步执行,但是由于软中断和tasklet是异步发送的,所以内核必须禁止它们。
Linux内核中的中断的更多相关文章
- Linux内核中的中断栈与内核栈的补充说明【转】
转自:http://blog.chinaunix.net/uid-12461657-id-3487463.html 原文地址:Linux内核中的中断栈与内核栈的补充说明 作者:MagicBoy2010 ...
- 向linux内核中添加外部中断驱动模块
本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...
- Linux内核中的GPIO系统之(3):pin controller driver代码分析
一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...
- 【转】 Linux内核中读写文件数据的方法--不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8193954 Linux内核中读写文件数据的方法 有时候需要在Linuxkernel--大 ...
- Linux内核中SPI总线驱动分析
本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...
- linux-2.6.26内核中ARM中断实现详解(转)
转载:http://www.cnblogs.com/leaven/archive/2010/08/06/1794293.html 更多文档参见:http://pan.baidu.com/s/1dDvJ ...
- Linux内核中的软中断、tasklet和工作队列具体解释
[TOC] 本文基于Linux2.6.32内核版本号. 引言 软中断.tasklet和工作队列并非Linux内核中一直存在的机制,而是由更早版本号的内核中的"下半部"(bottom ...
- (笔记)Linux内核中内存相关的操作函数
linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...
- 进程在Linux内核中的角色扮演
在Linux内核中,内核将进程.线程和内核线程一视同仁,即内核使用唯一的数据结构task_struct来分别表示他们:内核使用相同的调度算法对这三者进行调度:并且内核也使用同一个函数do_fork() ...
随机推荐
- C# @符号的多种使用方法
1.限定字符串用 @ 符号加在字符串前面表示其中的转义字符“不”被处理.如果我们写一个文件的路径,例如"D:/文本文件"路径下的text.txt文件,不加@符号的话写法如下:str ...
- Linux 锁
问题: 1.假如对某个文件加了锁/lock,但是程序退出时没有关闭锁,如果想在另外一个程序中用这个文件,如何办? 2.
- UVaLive 3708
题意:周长为10000的圆上等距分布n个雕塑,求再加入m个雕塑后,为使所有雕塑等距分布所需移动原来n个雕塑的最小总距离. 分析:计算相对距离. #include<cstdio> #incl ...
- 一些达成共识的JavaScript编码风格约定
如果你的代码易于阅读,那么代码中bug也将会很少,因为一些bug可以很容被调试,并且,其他开发者参与你项目时的门槛也会比较低.因此,如果项目中有多人参与,采取一个有共识的编码风格约定非常有必要.与其他 ...
- LESS学习总结
之前在工作过程中,用到了Less,一直没有将学习心得整理归纳,今天终于空出时间整理了一下. Less学习常用参考文档: Less 中文网 http://lesscss.cn/ 快速入门 | Les ...
- 配置tomcat时踩过的坑
conf/server.xml文件有2处地方容易踩坑: 1.<HOst>标签中的appBase名字,要看清,有些修改的版本,会把这个名字改成deploy,而eclipse默认部署的是web ...
- EditorLineEnds.ttr 受影响的D版本 Delphi 8-2010
http://stackoverflow.com/questions/25295980/delphi-2006-2010-error-cannot-create-file-c-users-admin- ...
- Spark Streaming揭秘 Day16 数据清理机制
Spark Streaming揭秘 Day16 数据清理机制 今天主要来讲下Spark的数据清理机制,我们都知道,Spark是运行在jvm上的,虽然jvm本身就有对象的自动回收工作,但是,如果自己不进 ...
- DB2分区表删除和添加分区
1.数据库版本 2.具体procedure DROP PROCEDURE DB2USER.TOOLS_PARTITION_TABLE_SHOW (VARCHAR ()); )) /********** ...
- UIImagePickerController拍照与摄像(转)
转载自:http://blog.sina.com.cn/s/blog_68edaff101019ppe.html (2012-11-23 14:38:40) 标签: ios iphone 拍照 摄像 ...