linux中断机制
❶ linux中断处理程序的方法
中断程序处理,使用kill或killall命令后面加上程序ID号(pid)或者程序名。查看程序ID使用ps 命令,然后,再用kill -9 <pid> 回车就可以把指定的程序中断了。再使用ps命令查看一下,原来的那个程序就没有了。
如果有多个名字相同的程序你想中断的话,就使用killall命令来指定程序名称,就可以中断多个相同名称的程序了。格式如下:
killall -9 httpd
我这里以中断httpd程序为例子。这样也可以中断程序执行。
❷ Linux几种中断信号的区别:HUP,INT,KILL,TERM,TSTP
Linux的HUP,INT,KILL,TERM,TSTP中断信号区别为:键入不同、对应操作不同、启用不同。
一、键入不同
1、HUP中断信号:HUP中断信号是当用户键入<Ctrl+X>时由终端驱动程序发送的信号。
2、INT中断信号:INT中断信号是当用户键入<Ctrl+I>时由终端驱动程序发送的信号。
3、KILL中断信号:KILL中断信号是当用户键入<Ctrl+Z>时由终端驱动程序发送的信号。
4、TERM中断信号:TERM中断信号是当用户键入<Ctrl+>时由终端驱动程序发送的信号。
5、TSTP中断信号:TSTP中断信号是当用户键入<Ctrl+T>时由终端驱动程序发送的信号。二、对应操作不同
1、HUP中断信号:HUP中断信号的对应操作为让进程挂起,睡眠。
2、INT中断信号:INT中断信号的对应操作为正常关闭所有进程。
3、KILL中断信号:KILL中断信号的对应操作为强制关闭所有进程。
4、TERM中断信号:TERM中断信号的对应操作为正常的退出进程。
5、TSTP中断信号:TSTP中断信号的对应操作为暂时停用进程。
三、启用不同
1、HUP中断信号:HUP中断信号发送后,可以重新被用户再次输入恢复启用进程。
2、INT中断信号:INT中断信号发送后,不可以重新被用户再次输入恢复启用进程。
3、KILL中断信号:KILL中断信号发送后,不可以重新被用户再次输入恢复启用进程。
4、TERM中断信号:TERM中断信号发送后,可以重新被用户再次输入启用进程。
5、TSTP中断信号:TSTP中断信号发送后,可以重新被用户再次输入继续使用进程。
❸ Linux如何及时响应外部中断
FPGA每隔100us给运行linux的ARM一个中断,要求在20us内响应中断,并读走2000*16bit的数据。
目前主要的问题是,当系统同时发生多个中断时,会严重影响linux对FPGA中断的响应时间。如何解决?
1、首先想到了ARM的FIQ,它可以打断IRQ中断服务程序,保证对外部FIQ的及时响应。但是发现linux只实现了IRQ,没有显示FIQ。
linux是从devicetree读取中断号,加入中断向量表的。
interrupts = <0x0 0x32 0x0>;中的第一个字段0表示非共享中断,非零表示共享中断,SDK产生的dts统一为0,此时第二字段的值比XPS中的小32;如果第一字段非零,则第二字段比XPS小16.
最后字段表示中断的触发方式。
IRQ_TYPE_EDGE_RISING =0x00000001,
IRQ_TYPE_EDGE_FALLING =0x00000002,
IRQ_TYPE_LEVEL_HIGH =0x00000004,
IRQ_TYPE_LEVEL_LOW =0x00000008,
很明显,devicetree根本没有提供通知linux有FIQ的渠道。
2、再来看linux的IRQ
linux的中断分为上半部和下半部,上半部运行在IRQ模式,会屏蔽所有中断,下半部运行在SVC模式,会重新打开中断。
也就是说,当一个中断的上半部正在运行时(不能再次响应中断),FPGA的中断是不能被linux响应的;
反过来,当FPGA中断的上半部正在运行时(不能再次响应中断),其他的中断也不能被linux响应;
unsigned long flags;
...
local_irq_save(flags);
....
local_irq_restore(flags);
3.
ARM有七种模式,我们这里只讨论SVC、IRQ和FIQ模式。
我们可以假设ARM核心有两根中断引脚(实际上是看不见的),一根叫 irq pin, 一根叫fiq pin.
在ARM的cpsr中,有一个I位和一个F位,分别用来禁止IRQ和FIQ的。
先不说中断控制器,只说ARM核心。正常情况下,ARM核都只是机械地随着pc的指示去做事情,当CPSR中的I和F位为1的时候,IRQ和FIQ全部处于禁止状态。无论你在irq
pin和fiq pin上面发什么样的中断信号,ARM是不会理你的,你根本不能打断他,因为他耳聋了,眼也瞎了。
在I位和F位为0的时候,当irq
pin上有中断信号过来的时候,就会打断arm的当前工作,并且切换到IRQ模式下,并且跳到相应的异常向量表(vector)位置去执行代码。这个过程是自动的,但是返回到被中断打断的地方就得您亲自动手了。当你跳到异常向量表,处于IRQ的模式的时候,这个时候如果irq
pin上面又来中断信号了,这个时候ARM不会理你的,irq
pin就跟秘书一样,ARM核心就像老板,老板本来在做事,结果来了一个客户,秘书打断它,让客户进去了。而这个时候再来一个客户,要么秘书不断去敲门问,要么客户走人。老板第一个客户没有会见完,是不会理你的。
但是有一种情况例外,当ARM处在IRQ模式,这个时候fiq pin来了一个中断信号,fiq
pin是什么?是快速中断呀,比如是公安局的来查刑事案件,那才不管你老板是不是在会见客户,直接打断,进入到fiq模式下,并且跳到相应的fiq的异常向量表处去执行代码。那如果当ARM处理FIQ模式,fiq
pin又来中断信号,又就是又一批公安来了,那没戏,都是执法人员,你打不断我。那如果这个时候irq
pin来了呢?来了也不理呀,正在办案,还敢来妨碍公务。
所以得出一个结论: IRQ模式只能被FIQ模式打断,FIQ模式下谁也打不断。
在打不断的情况下,irq pin 或 fiq pin随便你怎么发中断信号,都是白发。
所以除了fiq能打断irq以外,根本没有所谓中断嵌套的情况。
Linux不用FIQ,只用到了IRQ。但是我们有时候一个中断需要处理很长时间,那我们就需要占用IRQ模式那么长的时间吗?没有,linux在IRQ模式下只是简单的记录是什么中断,马上就切换回了SVC模式,换句话说,Linux的中断处理都是在SVC模式下处理的。
只不过SVC模式下的ISR上半部关闭了当前中断线,下半部才重新打开
❹ linux中断的问题
不会阻塞中断处理函数,因为disable_irq_nosync只是屏蔽中断触发,而不是屏蔽中断处理函数,
一般中断分为上半部和下半部,中断处理函数是在下半部,中断屏蔽只是在上半部;你应该先了解中断原理在来看代码,你应该先看一下《深入理解linux内核》这本书的中断部分
❺ 说明现代计算机采用中断的原因,阐述Linux操作系统的中断机制,它为什么采用内核机制
提高计算机的运行效率,准确的说是CPU的效率。举个例子,比如程序要进行格式化磁盘,那么这个操作要十分钟,那么如果没有中断机制,那么CPU要一直在那里等待操作的完成,之后再执行后面的任务。在等的时候任何请求的不响应。如果有中断,那么就可以让磁盘先去格式化,CPU就执行其他任务,当格式化完成时,以中断的方式打断CPU,通知CPU格式化操作完成。
❻ Linux 系统中的中断是不是没有中断优先级
关于中断嵌套:在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行的过程中,出现同一设备的中断或者不同设备的中断,这时候新的中断会被立即处理,还是被pending,等当前中断处理完成后,再做处理。在2.4和2.6内核里,关于这一块是否有什么不同。 一般申请中断的时候都允许开中断,即不使用SA_INTERRUPT标志。如果允许共享则加上 SA_SHIRQ,如果可以为内核熵池提供熵值(譬如你写的驱动是ide之类的驱动),则再加上 SA_SAMPLE_RANDOM标志。这是普通的中断请求过程。对于这种一般情况,只要发生中断,就可以抢占内核,即使内核正在执行其他中断函数。这里有两点说明:一是因为linux不支持 中断优先级,因此任何中断都可以抢占其他中断,但是同种类型的中断(即定义使用同一个 中断线的中断)不会发生抢占,他们会在执行本类型中断的时候依次被调用执行。二是所谓 只要发生中断,就可以抢占内核这句是有一定限制的,因为当中断发生的时候系统由中断门 进入时自动关中断(对于x86平台就是将eflags寄存器的if位置为0),只有当中断函数被执行 (handle_IRQ_event)的过程中开中断之后才能有抢占。 对于同种类型的中断,由于其使用同样的idt表项,通过其状态标志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同种类型的中断函数执行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函数被重入),对于不同的中断,则可以自由的嵌套。因此,所谓中断嵌套, 对于不同的中断是可以自由嵌套的,而对于同种类型的中断,是不可以嵌套执行的。以下简单解释一下如何利用状态标志来防止同种类型中断的重入:当某种类型的中断第一次发生时,首先其idt表项的状态位上被赋予IRQ_PENDING标志,表示有待处理。 然后将中断处理函数action置为null,然后由于其状态没有IRQ_INPROGRESS标志(第一次),故将其状态置上IRQ_INPROGRESS并去处IRQ_PENDING标志,同时将action赋予相应的中断处理函数指针(这里是一个重点,linux很巧妙的用法,随后说明)。这样,后面就可以顺利执行handle_IRQ_event进行中断处理,当在handle_IRQ_event中开中断后,如果有同种类型的中断发生,则再次进入do_IRQ函数,然后其状态位上加上IRQ_PENDING标志,但是由于前一次中断处理中加上的IRQ_INPROGRESS没有被清除,因此这里无法清除IRQ_PENDING标志,因此action还是为null,这样就无法再次执行handle_IRQ_event函数。从而退出本次中断处理,返回上一次的中断处理函数中,即继续执行handle_IRQ_event函数。当handle_IRQ_event返回时检查IRQ_PENDING标志,发现存在这个标志,说明handle_IRQ_event执行过程中被中断过,存在未处理的同类中断,因此再次循环执行handle_IRQ_event函数。直到不存在IRQ_PENDING标志为止。2.4和2.6的差别,就我来看,主要是在2.6中一进入do_IRQ,多了一个关闭内核抢占的动作,同时在处理中多了一种对IRQ_PER_CPU类型的中断的处理,其他没有什么太大的改变。这类IRQ_PER_CPU的中断主要用在smp环境下将中断绑定在某一个指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中断的时候。 其实简单的说,中断可以嵌套,但是同种类型的中断是不可以嵌套的,因为在IRQ上发生中断,在中断响应的过程中,这个IRQ是屏蔽的,也就是这个IRQ的中断是不能被发现的。 同时在内核的临界区内,中断是被禁止的 关于do_IRQ可能会丢失中断请求:do_IRQ函数是通过在执行完handle_IRQ_event函数之后判断status是否被设置了IRQ_PENDING标志来判断是否还有没有被处理的同一通道的中断请求。 但是这种方法只能判断是否有,而不能知道有多少个未处理的统一通道中断请求。也就是说,假如在第一个中断请求执行handle_IRQ_event函数的过程中来了同一通道的两个或更多中断请求,而这些中断不会再来,那么仅仅通过判断status是否设置了IRQ_PENDING标志不知道到底有多少个未处理的中断,handle_IRQ_event只会被再执行一次。这算不算是个bug呢? 不算,只要知道有中断没有处理就OK了,知道1个和知道N个,本质上都是一样的。作为外设,应当能够处理自己中断未被处理的情况。不可能丢失的,在每一个中断描述符的结构体内,都有一个链表,链表中存放着服务例程序关于中断中使用的几个重要概念和关系: 一、基本概念 1. 产生的位置 发生的时刻 时序 中断 CPU外部 随机 异步 异常 CPU正在执行的程序 一条指令终止执行后 同步 2.由中断或异常执行的代码不是一个进程,而是一个内核控制路径,代表中断发生时正在运行的进程的执行 中断处理程序与正在运行的程序无关 引起异常处理程序的进程正是异常处理程序运行时的当前进程 二、特点 (2)能以嵌套的方式执行,但是同种类型的中断不可以嵌套 (3)尽可能地限制临界区,因为在临界区中,中断被禁止 2.大部分异常发生在用户态,缺页异常是唯一发生于内核态能触发的异常 缺页异常意味着进程切换,因此中断处理程序从不执行可以导致缺页的操作 3.中断处理程序运行于内核态 中断发生于用户态时,要把进程的用户空间堆栈切换到进程的系统空间堆栈,刚切换时,内核堆栈是空的 中断发生于内核态时, 不需要堆栈空间的切换 三、分类 1.中断的分类:可屏蔽中断、不可屏蔽中断 2.异常的分类: 分类 解决异常的方法 举例 故障 那条指令会被重新执行 缺页异常处理程序 陷阱 会从下一条指令开始执行 调试程序
❼ Linux能不能在进程中控制某个中断开关
中断是内核级别的机制
应用程序在用户级别
用户级别权限低,是控制不了中断的。
除非,你自己写一个驱动(驱动也是运行在内核级别的),在这个驱动里去控制中断,是ok的
❽ linux系统中的中断指令是什么
什么是中断
Linux 内核需要对连接到计算机上的所有硬件设备进行管理,毫无疑问这是它的份内事。如果要管理这些设备,首先得和它们互相通信才行,一般有两种方案可实现这种功能:
轮询(polling) 让内核定期对设备的状态进行查询,然后做出相应的处理;中断(interrupt) 让硬件在需要的时候向内核发出信号(变内核主动为硬件主动)。
第一种方案会让内核做不少的无用功,因为轮询总会周期性的重复执行,大量地耗用 CPU 时间,因此效率及其低下,所以一般都是采用第二种方案 。
对于中断的理解我们先看一个生活中常见的例子:QQ。第一种情况:你正在工作,然后你的好友突然给你发送了一个窗口抖动,打断你正在进行的工作。第
二种情况:当然你有时候也会每隔 5 分钟就去检查一下 QQ
看有没有好友找你,虽然这很浪费你的时间。在这里,一次窗口抖动就可以被相当于硬件的中断,而你就相当于 CPU,你的工作就是 CPU
这在执行的进程。而定时查询就被相当于 CPU 的轮询。在这里可以看到:同样作为 CPU 和硬件沟通的方式,中断是硬件主动的方式,较轮询(CPU
主动)更有效些,因为我们都不可能一直无聊到每隔几分钟就去查一遍好友列表。
CPU
有大量的工作需要处理,更不会做这些大量无用功。当然这只是一般情况下。好了,这里又有了一个问题,每个硬件设备都中断,那么如何区分不同硬件呢?不同设
备同时中断如何知道哪个中断是来自硬盘、哪个来自网卡呢?这个很容易,不是每个 QQ 号码都不相同吗?同样的,系统上的每个硬件设备都会被分配一个
IRQ 号,通过这个唯一的 IRQ 号就能区别张三和李四了。
从物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如
8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,
处理器会通知 OS 已经产生中断。这样,OS
就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。
❾ Linux下如何强制中断一个程序的执行(利用按键,而不是kill命令)
Linux下强制中断一个程序的执行,利用按键,而不是kill命令。
可尝试以下方法:
1.CTRL + c中断。
2.CTRL + z暂停放到后台。
3.CTRL + d保存退出。
❿ LINUX软中断通信
我验证下阿...一不小心就fork多了..
刚开始我把kill的参数弄反了,信号和pid位置弄错了,调了半个小时,很郁闷..
你只是忽略了一点...,我也给忽略了。。。后来才想起来
你按下ctrl+C的时候,另外两个fork出来的进程,他们也会接到SIGINT。。。就退出了。。所以你要先在子进程里面忽略这个SIGINT信号,用signal(SIGINT,SIG_IGN)就OK了....
程序如下...
有解释,你可以自己看看...
#include"stdio.h"
#include"unistd.h"
#include"signal.h"
#include"sys/types.h"
#include"stdlib.h"
int k=0;
pid_t child1=0,child2=0;
void func_main(int sig);
void func_child1(int sig);
void func_child2(int sig);
int main()
{
while((child1=fork())==-1);
if(child1==0)
{
printf("child1 OK\n");
signal(SIGINT,SIG_IGN);
signal(SIGUSR1,func_child1);
sleep(60);
}
else if(child1 >0)
{
while((child2=fork())==-1);
if(child2==0)
{
printf("child 2 OK\n");
signal(SIGINT,SIG_IGN);//你按下ctrl+C,子进程也会接受到ctrl的信号...所以,子进程忽略
//所提子进程要忽略掉这个SIGINT信号
signal(SIGUSR2,func_child2);
sleep(60); //这里为了验证,如果进程没退出,40妙之后自动会退出的
//不然就得手动在终端里面kill掉这个进程了...
//有时候成了僵尸进程需要kill -9 才能杀死
}
else if(child2 >0)
{
signal(SIGINT,func_main);
printf("children forked OK...\n");
wait(0);
printf("child return...\n");
sleep(100);
return 0;
}
}
}
void func_main(int sig)
{
k++;
printf("to send signal\n");
//printf("child1=%d,child2=%d\n",child1,child2);
//if(k==1)
kill(child1,SIGUSR1);
//if(k==2) 加上这句,再按一次ctrl C,子进程2才会退出
就是你想要的效果了
kill(child2,SIGUSR2);
signal(SIGINT,SIG_DFL); //这里恢复ctrl+C的效果
//子进程退出之后,我们再按一次ctrl+C,当前的父进程就会像平常一样,退出。
}
void func_child1(int sig)
{
printf("child1 is killed by parent!\n");
exit(0);
}
void func_child2(int sig)
{
printf("child2 is killed by parent!\n");
exit(0);
}