Linux内核中断学习
1、内核中断概述
(1)在OS环境下编写中断处理函数与之前在裸机中编写中断处理函数的方式是不一样的,在Linux内核中提供了一套用来管理硬件中断资源的软件体系架构。
(2)在操作系统中,中断号与gpio、内存一样被认为是一种硬件资源,当我们需要使用某一个中断号时必须向操作系统申请中断资源,只有申请成功才能够使用,否则
就不能被自己使用。
2、中断的申请及释放
在Linux内核中提供了专用接口用来申请中断资源,这个接口就是:request_irq
(1)函数原型: request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
(2)参数说明:
irq: 需要申请的中断号,需要注意的是这里的中断号是内核中相关头文件中定义好的,与实际的硬件平台是相对应的,这个是内核移植的时候就做好的,不需要你去关系。
handler: 中断处理函数指针
flags: 用来描述中断属性的标志位,例如:中断的触发方式、本中断号是不是共享中断......更加详细的请参考 include\linux\interrupt.h 文件
name: 该中断的名字
dev: 对于这个参数,很多人说是用于共享中断(也就是多个中断源共有一个中断号),但是我觉得不是这么回事,当如果申请中断号的时候多个中断号是绑定在一个中断处理函数
中的时候,我们其实是可以通过dev传参来确定到底是那个中断号发生了中断事件,从而执行这个中断相关的代码;同样当我们在释放中断的时候也是要传入相同的参数。
内核中释放中断的函数: free_irq
(1)函数原型: void free_irq(unsigned int irq, void *dev_id)
(2)参数说明:
irq: 需要释放的中断号
dev_id: 这个参数就是request_irq中的dev
3、中断上下文
(1)第一首先需要明确的是:中断为什么需要分为上下文?
一般来说,中断处理函数代码执行的时间需要非常短,因为中断是不会参与内核调度,那么也就意味着进入中断必须要一直持有CPU不能释放,直到中断处理函数执行完毕才可以释放
CPU,如果中断处理函数执行时间过长必然会影响系统的实时性。
(2)那么一个很现实的问题就是:如果我们中断处理函数中必须要做很多的事情,没办法将时间缩短下来,该怎么办?
这就得用到今天讲的中断上下文。在Linux内核中将中断处理函数分文上下半部,也就是中断上下文。将中断处理函数分为上下半部之后,就是将其分为两个部分
(3)中断处理的注意点
1): 中断上下文,不能和用户空间数据交互
因为有可能导致休眠,而在中断中交出CPU之后是不能够在断点处获取到CPU继续执行下面的代码的,因为中断函数是不参与调度系统的,所以这样做的话就会导致中断函数
并不能够完美的执行。
2): 不能交出CPU(不能休眠、不能schedule交出CPU)
3): ISR运行时间尽可能短,越长则系统响应特性越差
4、中断下半部的两种解决方案
(1)下半部的处理策略1:tasklet(小任务)
初始化一个tasklet: DECLARE_TASKLET(name, func, data) // 定义一个名为name的tasklet任务,并将其初始化,func表示下半部绑定的函数,data表示传给func的参数
DECLARE_TASKLET_DISABLED(name, func, data) // 与上面一样,但是任务默认是关闭的
如何在中断的上半部开启tasklet任务:
tasklet_schedule(struct tasklet_struct *t) // 我们只需要在上半部函数中调用这个函数即可,t就是上面的name的指针
使能/禁止下半部:
tasklet_disable(struct tasklet_struct *t) // 禁止执行中断下半部
tasklet_enable(struct tasklet_struct *t) // 使能
(2)下半部的处理策略2:workqueue(工作队列)
初始化一个workqueue: struct work_struct irq_queue; INIT_WORK(&irq_queue, do_irq_queuework); // 先定义一个变量再初始化,do_irq_queuework表示绑定的函数
DECLARE_WORK(n, f) // 定义+初始化
如何在中断上半部开启workqueue工作队列:
schedule_work(struct work_struct *work);
5、中断上下半部处理原则
(1)必须立即进行紧急处理的极少量任务放入在中断的顶半部(上半部)中,此时屏蔽了与自己同类型的中断,由于任务量少,所以可以迅速不受打扰地处理完紧急任务。
(2)需要较少时间的中等数量的急迫任务放在tasklet中。此时不会屏蔽任何中断(包括与自己的顶半部同类型的中断),所以不影响顶半部对紧急事务的处理;同时又不会进
行用户进程调度,从而保证了自己急迫任务得以迅速完成。
(3)需要较多时间且并不急迫(允许被操作系统剥夺运行权)的大量任务放在workqueue中。此时操作系统会尽量快速处理完这个任务,但如果任务量太大,期间操作系统也会
有机会调度别的用户进程运行,从而保证不会因为这个任务需要运行时间将其它用户进程无法进行。
(4)可能引起睡眠的任务放在workqueue中。因为在workqueue中睡眠是安全的。在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,用workqueue
很合适。
/**************************************************************************************************************************/
未完待续。。。。。。。。。。。。。。。
Linux内核中断学习的更多相关文章
- Linux内核中断和异常分析(中)
在linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线.所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,上次讲到单片机的时候,我就讲到了单片机 ...
- Linux内核驱动学习(八)GPIO驱动模拟输出PWM
文章目录 前言 原理图 IO模拟输出PWM 设备树 驱动端 调试信息 实验结果 附录 前言 上一篇的学习中介绍了如何在用户空间直接操作GPIO,并写了一个脚本可以产生PWM.本篇的学习会将写一个驱动操 ...
- Linux 内核中断内幕
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html#resources Linux 内核中断内幕 ...
- Linux 内核list_head 学习
Linux 内核list_head 学习(一) http://www.cnblogs.com/zhuyp1015/archive/2012/06/02/2532240.html 在Linux内核中,提 ...
- Linux内核中断顶半部和底半部的理解
文章目录 中断上半部.下半部的概念 实现中断下半部的三种方法 软中断 软中断模版 tasklet tasklet函数模版 工作队列 工作队列函数模版 进程上下文和中断上下文 软中断和硬中断的区别 硬中 ...
- linux内核数据结构学习总结
目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...
- Linux内核驱动学习(六)GPIO之概览
文章目录 前言 功能 如何使用 设备树 API 总结 前言 GPIO(General Purpose Input/Output)通用输入/输出接口,是十分灵活软件可编程的接口,功能强大,十分常用,SO ...
- 羽夏看Linux内核——中断与分页相关入门知识
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作.如想转载,请把我的转载信息附在文章后面,并 ...
- linux内核--中断处理程序
一个设备的中断处理程序是它设备驱动程序的一部分--设备驱动程序是用于对设备进行管理的内核代码.中断处理程序与其他内核函数的真正区别在于,中断处理程序是被内核调用来响应中断的,而它们运行于我们称之为中断 ...
随机推荐
- Linux常见命令
du -sh 查看当前文件夹大小 tail -f /var/log/nginx/access.log 查看日志 vsFTPd Linux上面的ftp df -lh 查看磁盘 df -i 查看inode ...
- jQuery MiniUI开发系列之:创建组件对象
jQuery MiniUI可以使用Javascript和Html两种方式来创建对象. 1)Javascript创建对象 使用JavaScript创建对象,是最基本的方式,有如下几个要点: 1)使用ne ...
- insertAdjacentHTML方法示例
添加HTML内容与文本内容以前用的是innerHTML与innerText方法,最近发现还有insertAdjacentHTML和insertAdjacentText方法,这两个方法更灵活,可以在指定 ...
- Oracle 11.2.4.0 ACTIVE DATAGUARD 单实例安装(COPY创建备库)
Oracle 11.2.4.0 ADG 单实例安装(COPY创建备库) 规划: 主: OS: Linux Centos 6.5 X64 hostname:ORA11G-DG1 ipaddress:19 ...
- Webpack 入门指南 - 2.模块
这一次我们谈谈模块问题. 通常我们希望这个项目可以分为多个独立的模块,比如,上一次提高的 hello 函数,如果我们定义为一个模块,其它模块引用之后,直接调用就好了.在前端怎么使用模块呢?这可说来话长 ...
- Linux 网络基本配置
一.Linux网络配置文件 1. /etc/sysconfig/network-scripts/ifcfg-eth0 文件 在Red Hat系统中,系统网络设备的配置文件保存在/etc/syscon ...
- printf()输出
printf()函数是式样化输出函数, 一般用于向准则输出设备按规定式样输出消息.正在编写步骤时经常会用到此函数.printf()函数的挪用式样为: printf("<式样化字符串&g ...
- mac boot2docker certs not valid with 1.7
摘自:https://github.com/boot2docker/boot2docker/issues/824 An error occurred trying to connect: Get ht ...
- 15,SFDC 管理员篇 - 变更和部署
Setup | Deploy | Sandbox 通过在Production上建立Dev .Test 两套环境来 Sandbox 有四种类型 Developer Sandbox & Dev ...
- oracle批量修改多个表的数据
方法一 写PL/SQL,开cursor declare l_varID varchar2(20); l_varSubName varchar2(30); cursor mycur is sele ...