
信息与通信16信号一.ppt
68页信号〔一〕信号〔一〕第十六章第十六章1本章目标本章目标q中断q信号q信号与中断qsignal2中断中断q中断是系统对于异步事件的响应q中断信号q中断源q现场信息q中断处理程序q中断向量表3中断分类中断分类q硬件中断〔外部中断〕q外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断q软件中断〔内部中断〕q内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断4信号信号q信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动q信号是因为某些错误条件而产生的,比方内存段冲突、浮点处理器错误或者非法指令等q信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断5信号与中断信号与中断q信号与中断的相似点:q〔1〕采用了相同的异步通信方式;q〔2〕当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;q〔3〕都在处理完毕后返回到原来的断点;q〔4〕对信号或中断都可进行屏蔽q信号与中断的区别:q〔1〕中断有优先级,而信号没有优先级,所有的信号都是平等的;q〔2〕信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;q〔3〕中断响应是及时的,而信号响应通常都有较大的时间延迟。
6信号的名称是在头文件信号的名称是在头文件 signal.hsignal.h里定义的里定义的信号名称描述SIGABRT进程停止运行SIGALRM警告钟SIGFPE算述运算例外SIGHUP系统挂断SIGILL非法指令SIGINT终端中断SIGKILL停止进程(此信号不能被忽略或捕获)SIGPIPE向没有读者的管道写入数据SIGSEGV无效内存段访问信号名称信号名称信号名称描述SIGQUIT终端退出SIGTERM终止SIGUSR1用户定义信号1SIGUSR2用户定义信号2SIGCHLD子进程已经停止或退出SIGCONT如果被停止则继续执行SIGSTOP停止执行SIGTSTP终端停止信号SIGTOUT后台进程请求进行写操作SIGTTIN后台进程请求进行读操作信号名称信号名称进程对信号的三种响应进程对信号的三种响应q忽略信号不采取任何操作、有两个信号不能被忽略:SIGKILL和SIGSTOPq捕获并处理信号内核中断正在执行的代码,转去执行先前注册过的处q执行默认操作默认操作通常是终止进程,这取决于被发送的信号9signalsignalqtypedef void (*__sighandler_t) (int);q#define SIG_ERR ((__sighandler_t) -1)q#define SIG_DFL ((__sighandler_t) 0)q#define SIG_IGN ((__sighandler_t) 1)q函数原型:q__sighandler_t signal(int signum, __sighandler_t handler);q参数qsignal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出qhandler这个函数必须有一个int类型的参数〔即接收到的信号代码〕,它本身的类型是voidqhandler也可以是下面两个特殊值:qSIG_IGN屏蔽该信号qSIG_DFL恢复默认行为10总结总结q中断q信号q信号与中断qsignal11信号〔二〕信号〔二〕第十七章第十七章12本章目标本章目标q信号分类q可靠信号与不可靠信号q信号发送qpause13信号分类信号分类q可靠信号q不可靠信号q实时信号q非实时信号14linux信号机制根本上是从unix系统中继承过来的。
早期unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是:进程每次处理信号后,就将对信号的响应设置为默认动作在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反响以及信号可能丧失 linux支持不可靠信号,但是对不可靠信号机制做了改进:在调用完信号处理函数后,不必重新调用该信号的安装函数〔信号安装函数是在可靠机制上的实现〕因此,linux下的不可靠信号问题主要指的是信号可能丧失不可靠信号不可靠信号q随着时间的开展,实践证明了有必要对信号的原始机制加以改进和扩充所以,后来出现的各种unix版本分别在这方面进行了研究,力图实现"可靠信 号"由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丧失q同 时,信号的发送和安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()可靠信号可靠信号实时信号实时信号q早期Unix系统只定义了32种信号,Ret hat7.2支持64种信号,编号0-63(SIGRTMIN=31,SIGRTMAX=63),将来可能进一步增加,这需要得到内核的支持。
前32种信号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作如按键盘的CTRL ^C时,会产生SIGINT信号,对该信号的默认反响就是进程终止后32个信号表示实时信号,等同于前面阐述的可靠信号这保证了发送的多个实时信号都被接收实时信号是POSIX标准的一局部,可用于应用进程q非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号信号发送信号发送qkillqraiseq给自己发送信号raise(sig)等价于kill(getpid(), sig);qkillpgq给进程组发送信号killpg(pgrp, sig)等价于kill(-pgrp, sig);qsigqueueq给进程发送信号,支持排队,可以附带信息18pausepauseq将进程置为可中断睡眠状态然后它调用schedule(),使linux进程调度器找到另一个进程来运行qpause使调用者进程挂起,直到一个信号被捕获19总结总结q信号分类q可靠信号与不可靠信号q信号发送qpause20信号〔三〕信号〔三〕第十八章第十八章21本章目标本章目标q更多信号发送函数q可重入函数与不可重入函数q不可重入函数例如22更多信号发送函数更多信号发送函数qalarmqsetitimerqabort可重入函数可重入函数q为了增强程序的稳定性,在信号处理函数中应使用可重入函数。
q所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担忧数据是否会出错因为进程在收到信号后,就将跳转到信号处理函数去接着执行如果信号处理函数中使用了不可重入函数,那么信号处理函数可能会修改原来进程中不应该被修改的数据,这样进程从信号处理函数中返回接着执行时,可能会出现不可预料的后果不可再入函数在信号处理函数中被视为不平安函数q满足以下条件的函数多数是不可再入的:〔1〕使用静态的数据结构,如getlogin(),gmtime(),getgrgid(),getgrnam(),getpwuid()以及getpwnam()等等;〔2〕函数实现时,调用了malloc〔〕或者free()函数;〔3〕实现时使用了标准I/O函数的总结总结q更多信号发送函数q可重入函数与不可重入函数q不可重入函数例如25信号〔四〕信号〔四〕第十九章第十九章26本章目标本章目标q信号在内核中的表示q信号阻塞与未诀q信号集操作函数qsigprocmask27信号在内核中的表示信号在内核中的表示(2-1)q执行信号的处理动作称为信号递达〔Delivery〕,信号从产生到递达之间的状态,称为信号未决〔Pending〕。
进程可以选择阻塞〔Block〕某个信号被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作信号在内核中的表示可以看作是这样的: 信号在内核中的表示信号在内核中的表示(2-2)信号集操作函数信号集操作函数q#include
如果set是非空指针,那么更改进程的信号屏蔽字,参数how指示如何更改如果oset和set都是非空指针,那么先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字假设当前的信号屏蔽字为mask,下表说明了how参数的可选值sigprocmask(2-2)how参数的含义总结总结q信号在内核中的表示q信号阻塞与未诀q信号集操作函数qsigprocmask33信号〔五〕信号〔五〕第二十章第二十章34本章目标本章目标qsigaction函数qsigaction结构体qsigaction例如35sigactionq包含头文件
q返回值:函数成功返回0,失败返回-1sigaction结构体结构体q第二个参数最为重要,其中包含了对指定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉哪些函数等等struct sigaction {struct sigaction {void (*sa_handler)(int);void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void void (*sa_sigaction)(int, siginfo_t *, void *);*);sigset_t sa_mask;sigset_t sa_mask;int sa_flags;int sa_flags;void (*sa_restorer)(void);void (*sa_restorer)(void);};};总结总结qsigaction函数qsigaction结构体qsigaction例如38信号〔六〕信号〔六〕第二十一章第二十一章39本章目标本章目标qsigqueue函数qsigval联合体qsigqueue例如40sigqueue函数函数q功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。
q原型:int sigqueue(pid_t pid, int sig, const union sigval value);q参数q sigqueue的第一个参数是指定接收信号的进程id,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值q返回值成功返回0,失败返回-1 sigval联合体联合体qsigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组typedef union sigval { int sival_int; void *sival_ptr; }sigval_t; 总结总结qsigqueue函数qsigval联合体qsigqueue例如43信号〔七〕信号〔七〕第二十二章第二十二章44本章目标本章目标q三种不同精度的睡眠q三种时间结构qsetitimerqgetitimer45三种不同精度的睡眠三种不同精度的睡眠qunsigned int sleep(unsigned int seconds);qint usleep(useconds_t usec);qint nanosleep(const struct timespec *req, struct timespec *rem);46三种时间结构三种时间结构time_tstruct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */};struct timespec {time_t tv_sec; /* seconds */long tv_nsec; /* nanoseconds */};47setitimerq包含头文件
q返回值:成功返回0失败返回-1setitimerqITIMER_REAL:经过指定的时间后,内核将发送SIGALRM信号给本进程 qITIMER_VIRTUAL :程序在用户空间执行指定的时间后,内核将发送SIGVTALRM信号给本进程 qITIMER_PROF :进程在内核空间中执行时,时间计数会减少,通常与ITIMER_VIRTUAL共用,代表进程在用户空间与内核空间中运行指定时间后,内核将发送SIGPROF信号给本进程总结总结q三种不同精度的睡眠q三种时间结构qsetitimerqgetitimer50管道〔一〕管道〔一〕第二十三章第二十三章51本章目标本章目标q管道q匿名管道pipeq管道例如程序52q管道是Unix中最古老的进程间通信的形式q我们把从一个进程连接到另一个进程的一个数据流称为一个“管道〞什么是管道什么是管道q管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道q只能用于具有共同祖先的进程〔具有亲缘关系的进程〕之间进行通信;通常,一个管道由一个进程创立,然后该进程调用fork,此后父、子进程之间就可应用该管道管道限制管道限制q包含头文件
qO_NONBLOCK enable:read调用返回-1,errno值为EAGAINq当管道满的时候qO_NONBLOCK disable: write调用阻塞,直到有进程读走数据qO_NONBLOCK enable:调用返回-1,errno值为EAGAINq如果所有管道写端对应的文件描述符被关闭,那么read返回0q如果所有管道读端对应的文件描述符被关闭,那么write操作会产生信号SIGPIPEq当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性q当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性管道读写规那么管道读写规那么总结总结q管道读写规那么61管道〔三〕管道〔三〕第二十五章第二十五章62本章目标本章目标q命名管道〔FIFO〕q匿名管道与命名管道区别q命名管道的翻开规那么q命名管道例如程序63q管道应用的一个限制就是只能在具有共同祖先〔具有亲缘关系〕的进程间通信q如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道q命名管道是一种特殊类型的文件命名管道〔命名管道〔FIFO〕〕创立一个命名管道创立一个命名管道q命名管道可以从命令行上创立,命令行方法是使用下面这个命令:q$ mkfifo filenameq命名管道也可以从程序里创立,相关函数有:qint mkfifo(const char *filename,mode_t mode);匿名管道与命名管道匿名管道与命名管道q匿名管道由pipe函数创立并翻开。
q命名管道由mkfifo函数创立,翻开用openqFIFO〔命名管道〕与pipe〔匿名管道〕之间唯一的区别在它们创立与翻开的方式不同,一量这些工作完成之后,它们具有相同的语义命名管道的翻开规那么命名管道的翻开规那么q如果当前翻开操作是为读而翻开FIFO时qO_NONBLOCK disable:阻塞直到有相应进程为写而翻开该FIFOqO_NONBLOCK enable:立刻返回成功q如果当前翻开操作是为写而翻开FIFO时qO_NONBLOCK disable:阻塞直到有相应进程为读而翻开该FIFOqO_NONBLOCK enable:立刻返回失败,错误码为ENXIO总结总结q命名管道〔FIFO〕q匿名管道与命名管道区别q命名管道的翻开规那么q命名管道例如程序68。












