UC-day09中断,信号函数

合集下载

更新:中断函数PPT资料优秀版

更新:中断函数PPT资料优秀版
进制为:FF3F
/*********头文件区域*********/ #include <STC15.H> >
/******常量定义区域********/ #define BUZ P30 #define FOSC 18432000L #define T8KHZ (0xFFFF-FOSC/12/8000)
/*********变量定义区域*****/ unsigned char Count_Time;
/********函数申明***********/ void MCU_Init(void);
/*********主函数模块*******/ main(void) {
MCU_Init(); while(1) {} }
/******常量定义区域********/ #define BUZ P30 #define FOSC 18432000L #define T8KHZ (0xFFFF-FOSC/12/8000)
/*********变量定义区域*****/ unsigned char Count_Time;
/********函数申明***********/ void MCU_ቤተ መጻሕፍቲ ባይዱnit(void);
/********函数申明***********/ void MCU_Init(void);
/*********主函数模块*******/ main(void) {
MCU_Init(); while(1) {} }
/*******函数****************/
void MCU_Init(void) { IE &= ~0x80; //关中断
/*******函数****************/

Ucos学习之中断的应用

Ucos学习之中断的应用

在线学习好工作/Ucos学习之中断的应用在正常的情况下,是我们的主程序在运行,也就是我们的任务在运行,假设我们的主程序运行到某个地方的时候,产生了中断请求,产生了中断请求以后,CPU 来响应这个中断,它在响应这个中断之前呢,首先要做一件事就是现场的保护,这个很好理解,为什么这样呢?因为当我们在执行完中断函数以后,我们还有退回到原来的主函数中去,开始接着往下执行,那这样的话,必须保护这个现场,如果不保护这个现场,我们以后从中断函数退出的时候,那捏怎么知道从什么地方执行呢?所以,在这里,我们中断函数以后,要进行一个现场的保护。

现场保护要做的是什么事情呢?实际上就是保护CPU集成器,现场保护以后,CPU就转入中断函数执行,这个时候,就执行中断,执行中断也叫做ISR,执行完ISR以后,接下来我们要回到主程序执行,那它们之间的过程刚好是个相反的过程。

刚刚我们进行了一个现场保护,那么现在我们要进行一个现场恢复,恢复完现场以后,接下来我们要干的事情就是执行主程序,这个是我们整个中断的过程。

1)中断延迟中断延迟指的是,从产生中断开始,到执行第一条中断函数,这个时间被称作中断延迟时间。

也就是说,从这一时刻,我开始产生中断请求,到另一个时刻,我才执行中断函数,那么这段时间,就被称做中断延迟。

在这个中断延迟中,它都干了些什么事情,实际上就是一个CPU的现场保护。

2)中断响应比如说,某一个事件产生了,那件产生了多长时间以后才会来响应这个事件,这个就叫做中断响应过程,中断响应和中断延迟是有一定的区别的。

我们刚刚说中断延迟是从产生到延迟到执行第一条中断函数服务,而中断响应指的是产生中的请求然后到对这个中断进行处理,这个时间叫做中断响应。

3)中断恢复中断恢复指的是这个中断函数执行完毕以后到我们的主程序去执行这一段时间就是中断恢复的时间。

在我们不带操作系统的开发当中,也就是逻辑开发当中,我们中断延迟和中断响应是一样的。

假设我们跑了操作系统以后,跑了一个OS以后,我们看一下这个会变成什么样。

中断触发函数 -回复

中断触发函数 -回复

中断触发函数-回复中断触发函数,一种用于处理中断事件的编程方法。

在计算机系统中,中断是指在程序执行的过程中,由于硬件或软件的事件发生而打断正常的程序流程,优先执行中断处理程序,处理完后再返回原先的执行点继续执行。

中断触发函数就是指当接收到特定中断信号时,系统会自动调用预先定义好的函数来处理该中断事件。

本文将从中断的定义与原理、中断触发函数的作用与实现方法、以及开发中的应用场景等方面展开讨论。

一、中断的定义与原理中断是现代计算机系统中常见的一种事件触发方式。

当计算机系统发生特定的事件时,如外部设备的数据准备好、定时器的时间到达等,系统硬件会发送中断信号给CPU,打断当前正在执行的程序流程,CPU会立即转去执行与中断相关的处理程序。

中断的出现使得计算机系统具备了并发处理多个任务的能力,提高了系统的实时性和可靠性。

中断是由硬件和软件共同实现的。

硬件部分主要包括中断控制器、中断请求(IRQ)线和中断向量表。

中断控制器负责检测各个中断源的状态,并将中断信号发送给CPU。

中断请求线将中断信号传递给中断控制器。

中断向量表是一个用于存储中断处理程序入口地址的表格。

软件部分包括中断处理程序和中断控制程序。

中断处理程序是用于响应中断事件的程序,可以根据不同的中断源做出相应的处理。

中断控制程序负责对中断进行管理和调度。

二、中断触发函数的作用与实现方法中断触发函数是一种用于处理中断事件的编程方式,它可以使开发者能够更方便地编写和管理中断处理程序。

1. 作用:中断触发函数的主要作用是响应中断事件,并对该事件进行处理。

通过定义中断触发函数,系统能够根据中断信号自动调用相应的处理代码,无需手动编写中断处理程序的执行逻辑,提高了代码的可读性和维护性。

2. 实现方法:实现中断触发函数的方式因编程语言和操作系统而异。

在C语言中,通常可以通过向中断向量表中注册函数来实现中断触发函数。

当中断事件发生时,硬件会自动将处理程序入口地址从中断向量表中取出,并跳转至该地址执行。

中断服务函数嵌入式 -回复

中断服务函数嵌入式 -回复

中断服务函数嵌入式-回复什么是中断服务函数?在嵌入式系统中,中断是指在CPU执行程序的过程中,遇到某个特定的事件或条件,会打断正常的程序执行流程,转而去执行一个特定的处理函数。

而中断服务函数(Interrupt Service Routine,ISR)就是这个特定的处理函数。

中断服务函数是一段预编写的代码,在系统接收到中断信号时执行。

它的作用是快速响应中断,从而在时间上能够及时处理特定事件。

中断服务函数通常用来保存和恢复CPU的寄存器状态,并进行特定的处理逻辑,例如读取输入设备的数据、写入输出数据、更新系统状态等。

中断服务函数的执行方式是通过向CPU发送中断请求,然后由CPU 根据中断请求的类型选择相应的中断服务函数来执行。

每个中断请求都有一个对应的中断服务函数,通过这种方式,系统能够优先处理紧急或重要的事件,提高系统的实时性能。

中断服务函数的编写需要根据具体的硬件平台和中断源的特点而定。

一般来说,编写一个中断服务函数需要经历以下步骤:1. 确定中断源:首先要确定引发中断的具体事件或条件。

这可以是外部硬件设备触发的中断信号,如按键、定时器溢出等;也可以是内部软件事件触发的中断信号,如软件定时器超时、异常事件等。

2. 注册中断服务函数:将中断服务函数注册到相应的中断控制器或向量表中,以便在产生中断时能够被调用。

不同的嵌入式系统平台可能有不同的注册方法和接口,需要根据具体平台的文档进行操作。

3. 实现中断服务函数:编写中断服务函数的具体代码。

中断服务函数通常需要保存和恢复CPU的寄存器状态,这是因为在进入中断服务函数之前,CPU需要将当前的执行状态保存下来,以便在执行完中断服务函数后能够继续执行中断之前的程序。

此外,中断服务函数还需要根据具体需求进行特定的处理逻辑,比如读取输入设备的数据、更新系统状态等。

4. 中断优先级管理:在有多个中断源的情况下,需要对中断信号进行优先级排序和管理。

通过设置中断的优先级,可以确保高优先级的中断优先得到处理,避免低优先级的中断长时间得不到响应。

中断函数的使用

中断函数的使用

中断函数的使用:《单片机C语言编程与实例》中断函数通过使用interrupt关键字和中断编号0-4来实现。

使用该扩展属性的函数声明语法如下:返回值函数名interrupt nN对应中断源的编号中断编号告诉编译器中断程序的入口地址,它对应者IE寄存器中的使能位,即IE寄存器中的0位对应着的外部中断0,相应的外部中断0的中断编号是0。

当正在执行一个特定任务是,可能有更紧急的事情需要CPU处理,这就涉及到终端优先级,搞优先级的中断可以中断正在处理的底有限级中断程序,因而最好给每种优先级分配不同的寄存器组。

在c51中可以使用using制定的寄存器组,using后的变量为0-3的长整数,分别表示51单片机内的四个寄存器组。

中断函数的完整语法及实例如下:返回值函数名(【参数】)【模式】【重入】interrupt n [using n] Unsigned int interruptent;Unsigned char second;V oid time0(void)interrupt 1 using 2{if(++interruptent==4000) %计数到4000{second++; % 另一个计数器Interruptent=0; %计数器清零}}要是摸个中断源的申请得到相应,必须保证EA=1和相应的允许位为1定义中断服务函数的一般形式为::函数类型函数名(形式参数表)[interrupt n][using n]Interrupt 后面的n是中断号,n的取值范围为0-31,编译器从8n+3处产生中断向量。

11.111111外部中断例题:通过P1.7口电量发光二极管,然后外部输入一脉冲串,则发光二极管亮、暗交替#include <REGX51.H>Sbit P1_7=P1^7;V oid tnterrupt0()interrupt 0 using 2//定义定时器0{ P1_7=!P1^7;}V oid main(){EA=1;//开启总中断IT0=1;//外部中断0低电平触发EX0=1; //外部中断0P1_7=0;Do()while(1);}2222相套中断外部中断INT1触发后,启动计数器0,计数达到10次后停止计数,启动定时器1,由定时器1控制定时,由P1.7输出周期为200ms的方波性能好,接受2次中断后关闭方波发生器,P1.7置低。

UC-day09中断,信号函数.docx

UC-day09中断,信号函数.docx

今天内容:⑴中断的概念(2)信号的概念和函数2 3 7 9 11T•中断⑴概念表示暂时停止当前程序的执行,转血执任新的程序或者处理意外情况的过程⑵分类中断分为:硬件中断和软件中断、ctrl+c段错误2 •信号的概念和函数<2.1信号的初识⑴概念信号就是软中断,信号既可以作为进程间的一种通信方式,也可以屮断一个正在执行的程序,所以更多地用于处理意外情况⑵特点a.信号是异步的b.进程既可以处理信号,也可以发送信号给指定的进程c.每个信号都有一个名字,这些名字以SIG开头如:ctrl+c 是:SIGINT 值为:22.2信号的命令和分类⑴命令kill -1 =>表示査看当前操作系统中的所有信号(小括号里面是信号的值)tarenaSkiU ・11) SIGHUP2) SIGINT3) SIGQUIT4)SIGILL5) SI6TRAP6) SI6ABRT7) SI6BUS8) SI6FPE9)SIGKILL10) SIGUSR111) SI6SE6V12) SI6USR215) SIGPIPE14)SI6ALRM15) SIGTERM16) SI6STKFIT17) SIGCHLD18) SIGCONT19)SI6ST0P20) SI6TSTP21) SI6TTIN22) SI6TT0U25) SI6UR624)SI6XCPU25) SI6XFSZ26) SI6VTALRM27) SIGPROF28) SIGWINCH29掌握的信号:ctrl+c信号2 SIGINT默认处理是终止进程ctrl+\信号3 SIGQUIT默认处理是终止进程八退岀.(核心已转储)kill -9信号9 SIGKILL 不允许被捕捉,终止进程总线错误信号7 SIGBUS段错误信号门SIGSEGV其他信号:⑵分类一般来说,linux 系统屮信号:T64,不保证连续,unix 系统的信号和linux 系统可能有所不同,unix 系统中的信号一般是—48以linux 系统为例,做以下分类:1-31叫做不可靠信号,信号可能丢失,不支持排队(对能会出现插队的情况),又叫做 非实时信号34-64叫做可靠信号,信号不会丢失,支持排队,又叫做实时信号 <2.3信号的处理方式(1) 默认处理,绝大多数都是终止进程 (2) 忽略信号(3) 自定义处理信号,通过自定义函数进行处理注意:a •信号9只能进行默认处理,不能忽略,也不能进行自定义处理b •信号的发送受到用户的限制,一般来说,每个用户只能给自己的进程发信号,root 用户 I可以给所有进程发信号2.4信号的处理函数#inelude <signal ・h>typedef void (*sighandler_t)(int);//给函数指针其别名,给*sighandler 起别名 sighandler_t signal(int signum, sighandler_t handler);解析:typedef void (*)(int) sighandler_t;void (*)(int) signalfint signum, void (*)(int) handler);=>void (*)(int) signal(int signum, void (*handler)(int));=>void (*signal(int signum, void (*handler)(int)))(int)综上所述:=>signal是个函数=>函数的第一个参数是int类型的(信号值),第二个参数是函数指针类型的(处理方式) “函数的返回值是函数指针类型的二〉函数指针是一个指向参数为int,返回值为void的函数函数的使用:函数功能:设置指定信号的处理方式第一个参数:表示信号值/信号名称,int类型的第二个参数:对信号的处理方式,函数指针类型的SIG」GN ■忽略SIG_DFL-默认处理函数地址・调用指定的函数进行自定义处理返回值:成功返回Z前的处理方式,失败返回SIG.ERR 例子://signal函数的使用#inelude <stdio. h> #include <stdlib. h>程序输出:bash只发SIGINT SIGQUIT信号,对SIGINT处理是SIGJGN,SIGQUIT处理是fa (自定义)tarena$vi 01signal.c 山tarenalcc 01signal.c 终d 而 1tarena$a.out pid = 10455A C A C A C A C A C A C A C A C A C A C A C A C A\捕获到了信号 3 八\捕获到了信号3 八\捕获到了信号3 : 八\捕获到了信号3 八\捕茯到了信号3 八\捕茯到了信号3bash 发送kill -9 10455(进程号),进行自定义处理fa/旦是此信号不会被捕捉,默认终止进程练习:在主函数设置对信号2进行自定义处理,对信号3进行忽略处理,使用fork 创建子进程进 入无限循环,父进程结束,然后给子进程发送信号2和3看效杲〃练习ttinclude <stdio. h> ttincludc 〈unistd ・ h> #inelude <sys/types ・h> ^include <signal.h> #inelude <stdlib.h>return 0;//给子进程发送信号2,信号3tarena$vi 01signal.c z 屮 tarena$cc 01signal.c 终师 1 tarena$a.out pid = 10455tarena$kill -9 10455 终端'tarenajtarena$vi 01signal.c “ .山 tarena$cc 01signal.c 八细 1 tarena$a.out i pid = 10455AQA C A C A C A C A C A C A C A C A C A C A C A\捕获到了信号 3 A\捕茯到了信号3 人\捕获到了信号3 八捕获到了信号3 八\捕获到了信号3八捕获到了信号3 已杀死 tarena$|2.5父子进程对信号处理方式的比较(1)对于fork创建的子进程来说,完全照搬父进程对信号的处理方式,父进程忽略,子进程也忽略;父进程默认处理,子进程也默认处理;父进程白定义处理,子进程也白定义处理(2)对于vfork创建的子进程来说,父进程自定义,子进程默认处理;(不同)(子进程中用到execl()函数,自动跳转到别地方,在主函数中的自定义函数void fa(int signo)子进程就找不到了,所以就会默认处理父进程中的自定义信号)父进程忽略,子进程忽略;父进程默认处理,子进程也默认处理;2.6信号的发送方式⑴键盘发送(只能发送部分特殊信号,信号9就不能发送)ctrl+c ・> 信号2 SIGINTctrl+\ -> 信号3 SIGQUIT• • •(2)程序出错(只能发送部分特殊信号)段错误-> 信号11 SIGSEGV总线错误・>信号7 SIGBUS• • •⑶kill.信号值进程号(可以发送全部信号)⑷采用系统函数发送信号raise()/kill()/alarm()/sigqueue()2.7发送信号的函数(l)raise 函数(send a signal to the caller)#inelude <signal ・h> int raise(int sig);函数功能:表示向正在执行的进程/线程发送参数指定的信号,成功返回0,失败返回非0//raise 函数的使用 #inelude ^include #include ttinclude void fa(int signo) {printf (,z 捕获到了信号%d\n", signo);int main(void) {//先设置信号的处理方式 signal (2, fa);//10秒自后发送信号2 sleep(lO); raise(SIGINT); wh i le(l); return 0;tarena$cc 04raise.c tarena$a•out 捕获到了佰号2 M 扌甫获至ij 了佶号2 “扌甫获至U 了佰号2 M 捕获至U 了彳言号2 T :扌甫获至IJ 了彳莒号2 “扌甫获至(J 了信号2 八\退出(核41?己4专估) tarena$.(b) sleep 函数(sleep for the specified number of seconds)#inelude vunistd.h>unsig ned int sleep(unsigned int sec on ds);函数功能:表示让进程/线程按照参数指定的时间进入睡眠,如果睡醒了返冋0,如果没有睡醒被一个 不能忽略的信号打断,则返回剩余的秒数//raise 函数的使用 ^include <stdio. h> ^include <stdlib. h> #include <unistd ・h> #includc <signal ・h> void fa(int signo){printf (,z 捕获到了信号%d\n ,z , signo); }int main(void){//先设置信号的处理方式 signal (2, fci);<stdio.h> <stdlib.h> <unistd. h> <signal. h>〃10秒口后发送信号2int res=sleep(10):〃被一个不可忽略的信号打断,返回剩余秒数printf (^res=%d\n,z, res);raise(S1G1NT):wh i1e(1);return 0;}tarena$a•outY捕获到了信号2 res = 7捕获到了信号2(2)kill 函数(send signal to a process)#inelude <sys/types.h>#inelude <signal・h>int kill(pid_t pid, int sig);第一个参数:进程号正数・表示给指定单一进程发信号(单发,掌握)0 ・表示发送给与正在运行的进程同组的每一个进程(了解)-1 -表示把信号发送到每一个可以被发送信号的进程中,除了进程l(init进程,了解)<-1 -表示发送给进程组id为-pid的每一个进程 (了解)第二个参数:信号0 ・表示检查指定的进程/进程组的存在性函数功能:给指定的进程发送指定的信号//kill函数的使用^include <stdio. h>#include <stdlib.h> #inelude <signal. h> #include <sys/types.h> #include <unistd.h> void fa(int signo){ printf (z/捕捉到信号%d\n z,, signo); }i nt main(voi d) {return 0;tarena$a ・ out父进程10836给子进程10837发送信号50 捕获到了信号50tarena$|(3)alarm 函数(set an alarm clock for delivery of signal)#inelude <unistd.h>unsigned int alarm(unsigned int sec on ds);函数功能:表示经过参数指定的秒数Z后发送SIGALARM信号,函数返回Z前闹钟剩余的秒数,Z前没有闹钟则返回0printf (,z res=%d\res) ;//3 while(l);return 0;tarena$cc 06alarm.c tarena$a.out res = 0 res = 3 捕获到了借号14A Ctarena$ls例子2://alarm函数的使用ttinclude〈stdio. h> ttinclude <stdlib.h> #include <unistd.h> #inelude <signal. h> void fa(int signo) {printf C捕获到的信号%d\n〃,signo);〃每隔一秒触发一次,类似于递归alarm(l);}int main(voicl) {〃设置SIGALRM信号进行自定义处理signal(STGALRM, fa);//5秒Z后发送SIGALRM信号int res=alarm(5);printf C,res=%d\n//, res);〃之前没有闹钟,返回0 wh订e(l);return 0;}tarena$a.out res = 0 res = 3 捕获到了信号14 捕获到了信号14 捕获到了信号M 捕获到了信号14 捕获到了信号14 捕获到了信号14 捕获到了信号14 捕获到了信号142.8信号集的概念和使用⑴概念信号集・表示信号的集合信号集的数据类型:sigset.t 128个字节typedef struct {unsigned long int _val[(1024 / (8 * sizeof(unsigned long int)))];} _sigset_t;typedef _sigset_t sigset_t;linux 系统表示信号的范围「64,采用最节省内存的方式表示信号,让每一个二进制位来代 表一个信号,则8个字节足够,而sigset_t 本质上就是占用128个字节,然后釆用每一个二进 制位表示一个信号<stdio. h> <stdlib. h> <unistd. h> <signal. h>int m3in(void) {printf (/zsigset_t=%d\n 〃,sizeof (segset_t)) ;//128 return 0; }____________________________________________tarenajcc 07sigset.c tarena$a.out sigset_t = 128 ta ・E 07sigset ・c ・o 07sigset.i tarenajvi 07sigset ・i|底层的实现方法(2)基本操作#include <signal.h>sigemptyset()・清空信号集(二进制置为0) int sigemptyset(sigset^t *set); sigfillset()-填满信号集(二进制置为1)例子 vi 07sigset.c//信号集的概念和基本操作 ttinclude WincludeWinclude #inelude int main1156 11 typedef struct 57 1158 11591160 unsigned long ir t _val 〔(1024 / (8 size of unsigned long int))J];} __@igset.t; * 35 7usr/include/i586-linux-gnu/sys/select. h" 2 3 4int sigfiUset(sigset_t *set);sigaddset()-增加一个信号(对应二进制置为1) int siqaddset(siqset_t *set r int signum);sigdelsetf) ■删除一个信号(对应二进制置为0) int siqdelset(siqset_t *set r int signum): <stdio. h>sigismemberf)-查找是否存在某个信号int sigismember(const sigset_t *set> int signum);//信号集的概念和基本操作WincludeWinclude#ineludeSincludcint main<stdlib. h>〈unistd. h><signa 1. h>—in (void) {printf ("sigse二%d\n〃,sizeof(segset_t));//128 sigset_t set;//先定义信号集printf (zz set=%ld z,, set);〃清空信号集sigemptyset(&set); printf (〃set二%ld〃,set);〃增加信号到信号集中,第二位二进制置为1 sigaddset(&set, 2);printf (zz sct=%ld,/, set) ;//2 sigaddset(&set, 3);//2+4二6 printf(〃set二%ld〃,set);sigaddset(&set, 7);//6+64二70 printf (zz set=%ld z,, set);sigdelset(&set,3); printf (,,set=%ld,,> set) ;//70-4二66 il'(sigismember(&sel, 3)) printfC信号3存在信号集屮\n〃);if(sigsimumbcr (&set,7)) printfC信号7存在信号集中\『);feturn 0;}因为是set是sigset.t类型,不是long int类型•这里为了省事这么输出tarena$cc 07sigset・c07sigset.c:在函数'main'中:07sigset.c:11:警吿:格式'机d'JR要类型'long int*,但实参2的类型为-sigset.f1tarena$|tarena$a.out sigset.t = 128 set = -1078593826 set s 0 set = 2 set = 6set = 70 1set = 66 信号7存在信号集中tarenaS2.9信号的屏蔽在某些特殊情况下不允许程序的执行被信号打断,则需要对信号进行屏蔽来解决此问题(l)sigprocmask 函数(examine and change blocked signals(信号集))#inelude <signal.h>int sigprocmask(int how, const sigset_t* set, sigset_t *oldset); 第一个参数:处理方式SIG_BLOCK: ABC CDE 二〉ABCDE(新+1日)SIG_UNBLOCK: ABC CDE=>AB(I口■新)SIG_SETMASK: ABC CDE二〉CDE(新的替换旧的,掌握)第二个参数:设置新的信号屏蔽字(信号集)第三个参数:带出旧的信号屏蔽字(信号集)函数功能:主要用于设置新的信号屏蔽字,带出之前的信号屏蔽字(2)sigpending 函数#inelude <signabint sigpending(sigset_t *set);函数功能:获収在信号屏蔽期间來过的信号//sigprocmask函数的使用#include <stdio・ h>#inelude <stdlib.h>#include 〈unistd.h>sigprocmask (SIG_SETMASK, &old, NULL); return 0;注意:(1) 信号屏蔽并不是删除信号,而只是把信号暂时存起来,等信号屏蔽解除之后还是可以处 理的(2) —般使用原则:先设置新的信号屏蔽字,屏蔽工作完成后再恢复旧的 作业:自己查询一下sigaction 函数明日预报:⑴信号(2)进程间的通信 50是可靠信号,信号重复发送, 会重复处理 tarenaja.out pid =11252 捕获到了信号3 没有信号屏蔽,睡F开始信号屏蔽old = 0:总篦IS 了美觉,信号屏溯始解捕获到了信号50捕获到了信号50捕获到了信号50捕茯到了信号3捕获到了信号2 3,2为不可靠信号,信号发很多次 时,只处理一次 信号屏蔽期间,发送的信号不是被丢失,然是暂时储 存,等到尿蔽结束,将储存的信号输出出来。

中断函数的作用

中断函数的作用

中断函数的作用中断函数是计算机中一种特殊的函数,它的作用是在特定的事件发生时中断正在执行的程序,转而执行中断函数。

中断函数的作用在于响应外部事件,处理特定的任务,并在完成后返回到原来的程序继续执行。

下面将从多个方面介绍中断函数的作用。

1. 响应外部事件中断函数主要用于响应外部事件,例如用户的输入、硬件设备的信号等。

通过中断函数,计算机可以在需要时立即中断正在执行的程序,并执行特定的任务。

这使得计算机能够实时响应外部事件,提高了系统的效率和性能。

2. 处理异常情况中断函数还可以用于处理异常情况,例如除零错误、内存访问错误等。

当出现这些异常情况时,计算机会触发相应的中断,并执行预设的中断函数来处理异常。

这有助于保护计算机系统的稳定性和安全性。

3. 实现多任务处理中断函数的作用之一是实现多任务处理。

在多任务操作系统中,当一个任务正在执行时,其他任务可以通过中断函数插入并执行。

这样可以实现多个任务之间的切换和并发执行,提高系统的效率和响应能力。

4. 提供硬件接口中断函数还可以用于提供硬件接口,使得软件能够与硬件进行交互。

例如,当需要读取硬盘数据时,操作系统可以通过中断函数发送读取指令,并在数据准备好后触发中断来通知操作系统。

这样可以简化软件与硬件之间的通信过程,提高系统的可扩展性和可维护性。

5. 实现定时和计时功能中断函数还可以用于实现定时和计时功能。

通过设置定时器,当计时器到达指定的时间时,会触发中断函数。

这可以用于实现定时任务的执行、实现精确的计时功能等。

中断函数在计算机系统中具有重要的作用。

它能够响应外部事件,处理异常情况,实现多任务处理,提供硬件接口,以及实现定时和计时功能。

中断函数的作用使得计算机系统能够更加高效、稳定和安全地运行,为用户提供更好的使用体验。

中断服务函数嵌入式 -回复

中断服务函数嵌入式 -回复

中断服务函数嵌入式-回复中断服务函数,在嵌入式系统中扮演着重要的角色。

它们允许处理器在发生中断事件时实时响应,并执行相关的操作。

本文将详细介绍中断服务函数的概念、工作原理及其在嵌入式系统中的应用。

一、中断服务函数的概念中断服务函数是嵌入式系统中用于处理中断事件的一段代码。

中断事件包括外部源(如外设)发送的信号,以及内部源(如系统时钟、定时器等)触发的事件。

中断服务函数负责处理这些事件,执行相应的操作,并将处理结果返回给主程序。

中断服务函数的主要作用是实现实时响应。

在嵌入式系统中,时间非常关键。

当系统需要因为某些事件及时做出反应时,中断服务函数能够立即执行相应处理,而不需要等待主程序的调度。

二、中断服务函数的工作原理中断服务函数的工作原理可分为以下几个步骤:1. 中断源产生中断信号:嵌入式系统中存在多种中断源,如外设中断、定时器中断等。

当中断源检测到特定事件发生时,会产生中断信号。

2. 保存现场:在真正执行中断服务函数之前,首先需要保存当前的执行环境。

这包括保存寄存器的值、栈指针等关键信息,以便在中断服务函数执行完毕后能够正确恢复现场。

3. 跳转至中断服务函数:一旦中断信号产生,处理器会暂停正在执行的任务,跳转至中断服务函数。

中断服务函数是事先定义好的,通常保存在特定的中断向量表中。

4. 执行中断服务函数:中断服务函数执行与普通函数类似,但有一些特殊要求。

首先,需要在尽可能短的时间内完成处理,以避免对系统的影响。

其次,中断服务函数中不能有长时间的延迟操作,否则可能影响系统的实时性。

最后,中断服务函数要准确处理中断事件,执行相应的操作。

5. 恢复现场:中断服务函数执行完毕后,需要恢复之前保存的执行环境。

这样才能保证主程序在中断返回后可以继续执行,而不会出现异常情况。

6. 返回中断处理:恢复现场后,处理器会将控制权返回给中断触发的地方继续执行。

这可能是中断指令之后的下一条指令,或者主程序被暂停的位置。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

-----------------------------------------------今天内容:(1)中断的概念(2)信号的概念和函数 2 3 7 9 111.中断(1)概念表示暂时停止当前程序的执行,转而执行新的程序或者处理意外情况的过程(2)分类中断分为:硬件中断和软件中断ctrl+c 段错误2.信号的概念和函数2.1 信号的初识(1)概念信号就是软中断,信号既可以作为进程间的一种通信方式,也可以中断一个正在执行的程序,所以更多地用于处理意外情况(2)特点a. 信号是异步的b. 进程既可以处理信号,也可以发送信号给指定的进程c. 每个信号都有一个名字,这些名字以SIG开头如:ctrl+c 是:SIGINT 值为:22.2 信号的命令和分类(1)命令kill -l => 表示查看当前操作系统中的所有信号(小括号里面是信号的值)掌握的信号:ctrl+c信号2 SIGINT默认处理是终止进程ctrl+\信号3SIGQUIT 默认处理是终止进程kill -9 信号9SIGKILL不允许被捕捉,终止进程总线错误信号7SIGBUS段错误信号11SIGSEGV其他信号:(2)分类一般来说,linux系统中信号1~64,不保证连续,unix系统的信号和linux系统可能有所不同, unix系统中的信号一般是1~48以linux系统为例,做以下分类:1~31叫做不可靠信号,信号可能丢失,不支持排队(可能会出现插队的情况),又叫做非实时信号34~64叫做可靠信号,信号不会丢失,支持排队,又叫做实时信号2.3 信号的处理方式(1)默认处理,绝大多数都是终止进程(2)忽略信号(3)自定义处理信号,通过自定义函数进行处理注意:a.信号9只能进行默认处理,不能忽略,也不能进行自定义处理b.信号的发送受到用户的限制,一般来说,每个用户只能给自己的进程发信号,r oot用户可以给所有进程发信号2.4 信号的处理函数#include <signal.h>typedef void (*sighandler_t)(int);//给函数指针其别名,给*sighandler起别名sighandler_t signal(int signum, sighandler_t handler);解析:typedef void (*)(int) sighandler_t;void (*)(int) signal(int signum, void (*)(int) handler);=>void (*)(int) signal(int signum, void (*handler)(int));=>void (*signal(int signum, void (*handler)(int)))(int)综上所述:=>signal是个函数=>函数的第一个参数是int类型的(信号值),第二个参数是函数指针类型的(处理方式)=>函数的返回值是函数指针类型的=>函数指针是一个指向参数为int,返回值为void的函数函数的使用:函数功能:设置指定信号的处理方式第一个参数:表示信号值/信号名称,int类型的第二个参数:对信号的处理方式,函数指针类型的SIG_IGN- 忽略SIG_DFL - 默认处理函数地址- 调用指定的函数进行自定义处理返回值:成功返回之前的处理方式,失败返回SIG_ERR例子://signal函数的使用#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>#include<sys/types.h>void fa(int signo){printf("捕获到了信号%d\n",signo);signal(“3,SIG_DFL”);//信号第一次是自定义处理,信号第二次是默认处理}int main(void){//设置对信号2的处理方式为忽略,注意是终端发送信号(bash)signal(2,SIG_IGN);//设置对信号3,进行自定义处理signal(SIGQUIT,fa);//设置对信号9,进行自定义处理,不好使signal(SIGKILL,fa);printf("pid=%d\n",getpid);while(1);}程序输出:bash只发SIGINT SIGQUIT信号,对SIGINT处理是SIG_IGN,SIGQUIT处理是fa(自定义)终端1bash发送kill -9 10455(进程号),进行自定义处理fa,但是此信号不会被捕捉,默认终止进程终端1终端1终端2练习:在主函数设置对信号2进行自定义处理,对信号3进行忽略处理,使用fork创建子进程进入无限循环,父进程结束,然后给子进程发送信号2和3看效果//练习#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<signal.h>#include<stdlib.h>void fa(int signo){printf("捕捉到了信号%d\n",signo);}int main(void){printf("父进程ID=%d\n",getpid());//对信号2进行自定义处理signal(2,fa);//对信号3进行忽略处理signal(SIGQUIT,SIG_IGN);//创建子进程,子进程进入死循环pid_t pid=fork();if(0==pid){printf("子进程ID=%d\n",getpid());while(1);}printf("父进程结束,子进程未结束\n");return0;//给子进程发送信号2,信号3}ctrl +c发给的是bash,并不是子进程kill可以指定发何种信号2.5 父子进程对信号处理方式的比较(1)对于fork创建的子进程来说,完全照搬父进程对信号的处理方式,父进程忽略,子进程也忽略;父进程默认处理,子进程也默认处理;父进程自定义处理,子进程也自定义处理(2)对于vfork创建的子进程来说,父进程自定义,子进程默认处理;(不同)(子进程中用到execl()函数,自动跳转到别地方,在主函数中的自定义函数void fa(int signo)子进程就找不到了,所以就会默认处理父进程中的自定义信号)父进程忽略,子进程忽略;父进程默认处理,子进程也默认处理;2.6 信号的发送方式(1)键盘发送(只能发送部分特殊信号,信号9就不能发送)ctrl+c -> 信号2 SIGINTctrl+\ -> 信号3 SIGQUIT...(2)程序出错(只能发送部分特殊信号)段错误-> 信号11 SIGSEGV总线错误->信号7 SIGBUS...(3)kill -信号值进程号(可以发送全部信号)(4)采用系统函数发送信号raise()/kill()/alarm()/sigqueue()2.7 发送信号的函数(1)raise函数(send a signal to the caller)#include <signal.h>int raise(int sig);函数功能:表示向正在执行的进程/线程发送参数指定的信号,成功返回0,失败返回非0例子://raise函数的使用#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>void fa(int signo){printf("捕获到了信号%d\n",signo);}int main(void){//先设置信号的处理方式signal(2,fa);//10秒自后发送信号2sleep(10);raise(SIGINT);while(1);return0;}(b) sleep函数(sleep for the specified number of seconds)#include <unistd.h>unsigned int sleep(unsigned int seconds);函数功能:表示让进程/线程按照参数指定的时间进入睡眠,如果睡醒了返回0,如果没有睡醒被一个不能忽略的信号打断,则返回剩余的秒数//raise函数的使用#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>void fa(int signo){printf("捕获到了信号%d\n",signo);}int main(void){//先设置信号的处理方式signal(2,fa);//10秒自后发送信号2int res=sleep(10);//被一个不可忽略的信号打断,返回剩余秒数printf("res=%d\n",res);raise(SIGINT);while(1);return0;}(2)kill函数(send signal to a process)#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);第一个参数:进程号正数- 表示给指定单一进程发信号(单发,掌握)0 - 表示发送给与正在运行的进程同组的每一个进程(了解)-1 - 表示把信号发送到每一个可以被发送信号的进程中,除了进程1(init进程,了解) <-1 - 表示发送给进程组id为-pid的每一个进程(了解)第二个参数:信号0 - 表示检查指定的进程/进程组的存在性函数功能:给指定的进程发送指定的信号//kill函数的使用#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<sys/types.h>#include<unistd.h>void fa(int signo){printf("捕捉到信号%d\n",signo);}int main(void){pid_t pid=fork();if(-1==pid)perror("fork"),exit(-1);if(0==pid){//自定义处理信号50signal(50,fa);while(1);}sleep(1);//父进程判断子进程是否存在if(0==kill(pid,0)){printf("父进程%d给子进程%d发送信号50\n",getpid(),pid);kill(pid,50);}return0;}(3)alarm函数(set an alarm clock for delivery of signal)#include <unistd.h>unsigned int alarm(unsigned int seconds);函数功能:表示经过参数指定的秒数之后发送SIGALARM信号,函数返回之前闹钟剩余的秒数,之前没有闹钟则返回0参数为0时,不会设置新的闹钟,取消之前的闹钟//alarm函数的使用#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>void fa(int signo){printf("捕获到的信号%d\n",signo);}int main(void){//设置SIGALRM信号进行自定义处理signal(SIGALRM,fa);//5秒之后发送SIGALRM信号int res=alarm(5);printf("res=%d\n",res);//之前没有闹钟,返回0sleep(2);res=alarm(10);printf("res=%d\n",res);//3while(1);return0;}例子2://alarm函数的使用#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>void fa(int signo){printf("捕获到的信号%d\n",signo);//每隔一秒触发一次,类似于递归alarm(1);}int main(void){//设置SIGALRM信号进行自定义处理signal(SIGALRM,fa);//5秒之后发送SIGALRM信号int res=alarm(5);printf("res=%d\n",res);//之前没有闹钟,返回0 while(1);return0;}2.8 信号集的概念和使用(1)概念信号集- 表示信号的集合信号集的数据类型: sigset_t 128个字节typedef struct{unsigned long int __val[(1024 / (8 *sizeof (unsigned long int)))];} __sigset_t;typedef __sigset_t sigset_t;linux系统表示信号的范围1~64,采用最节省内存的方式表示信号,让每一个二进制位来代表一个信号,则8个字节足够,而sigset_t本质上就是占用128个字节,然后采用每一个二进制位表示一个信号例子vi 07sigset.c//信号集的概念和基本操作#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>int main(void){printf("sigset_t=%d\n",sizeof(segset_t));//128return0;}底层的实现方法(2)基本操作#include <signal.h>sigemptyset() - 清空信号集(二进制置为0)sigfillset() - 填满信号集(二进制置为1)sigaddset() - 增加一个信号(对应二进制置为1)sigdelset() - 删除一个信号(对应二进制置为0)sigismember() - 查找是否存在某个信号例子://信号集的概念和基本操作#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>int main(void){printf("sigset_t=%d\n",sizeof(segset_t));//128sigset_t set;//先定义信号集printf("set=%ld",set);//清空信号集sigemptyset(&set);printf("set=%ld",set);//增加信号到信号集中,第二位二进制置为1sigaddset(&set,2);printf("set=%ld",set);//2sigaddset(&set,3);//2+4=6printf("set=%ld",set);sigaddset(&set,7);//6+64=70printf("set=%ld",set);sigdelset(&set,3);printf("set=%ld",set);//70-4=66if(sigismember(&set,3))printf("信号3存在信号集中\n");if(sigsimumber(&set,7))printf("信号7存在信号集中\n");return0;}因为是set是sigset_t类型,不是long int类型.这里为了省事这么输出2.9 信号的屏蔽在某些特殊情况下不允许程序的执行被信号打断,则需要对信号进行屏蔽来解决此问题(1)sigprocmask函数(examine and change blocked signals(信号集))#include <signal.h>int sigprocmask(int how, const sigset_t* set, sigset_t *oldset);第一个参数:处理方式SIG_BLOCK: ABC CDE =>ABCDE(新+旧)SIG_UNBLOCK: ABC CDE=>AB(旧-新)SIG_SETMASK:ABC CDE=>CDE(新的替换旧的,掌握)第二个参数:设置新的信号屏蔽字(信号集)第三个参数:带出旧的信号屏蔽字(信号集)函数功能:主要用于设置新的信号屏蔽字,带出之前的信号屏蔽字(2)sigpending 函数#include <signal>int sigpending(sigset_t *set);函数功能:获取在信号屏蔽期间来过的信号例子://sigprocmask函数的使用#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>#include<sys/types.h>void fa(int signo){printf("捕获到了信号%d\n",signo);}int main(void){printf("当前进程的进程号%d\n",getpid());//设置对信号2,信号3,信号50进行自定义处理signal(2,fa);signal(3,fa);signal(50,fa);int res=sleep(20);//返回未完成的时间if(0!=res){printf("没有信号屏蔽,睡眠别唤醒,所以睡了%d秒\n",20-res);}printf("--------------------------------\n");printf("开始信号屏蔽\n");//准备信号集,作为函数的参数sigset_t set,old;//清空信号集sigemptyset(&set);sigemptyset(&old);//将要屏蔽的信号放入信号集中sigaddset(&set,2);sigaddset(&set,3);sigaddset(&set,50);//调用函数进行信号的屏蔽if(-1==sigprocmask(SIG_SETMASK,&set,&old)){perror("sigprocmask"),exit(-1);}printf("old=%ld\n",old);res=sleep(20);if(0==res)printf("总算睡了个美觉,信号屏蔽开始结束\n");//判断屏蔽期间信号,到底来没来过sigset_t pend;sigpending(&pend);if(sigismenber(&pend,2))printf("信号2来过\n");if(sigismenber(&pend,3))printf("信号3来过\n");if(sigismenber(&pend,50))printf("信号50来过\n");//恢复系统默认的屏蔽方式sigprocmask(SIG_SETMASK,&old,NULL);return 0;}注意:(1)信号屏蔽并不是删除信号,而只是把信号暂时存起来,等信号屏蔽解除之后还是可以处理的(2)一般使用原则:先设置新的信号屏蔽字,屏蔽工作完成后再恢复旧的作业:自己查询一下sigaction 函数明日预报:(1)信号(2)进程间的通信信号屏蔽期间,发送的信号不是被丢失,然是暂时储存,等到屏蔽结束,将储存的信号输出出来50是可靠信号,信号重复发送,会重复处理 3,2为不可靠信号,信号发很多次时,只处理一次。

相关文档
最新文档