您的位置:首页 > 编程语言

UNIX环境高级编程--信号(十)

2013-09-22 20:12 288 查看

一、引言

信号时软件中断,信号听了一种处理异步事件的方法:终端用户键入中断键,则会通过信号机构停止一个程序。在早期的版本中提供的信号模型并不可靠。信号可能被丢失,而且在执行临界区代码时,进程很难关闭所选择的信号。本章先对信号机制进行综述,并说明每种信号的一般用法,

二、信号的概念

每个信号都有一个名字。名字都已三个字符SIG开头,例如SIGABRE是夭折信号,进程调用abort函数时产生这种信号,在头文件<signal.h>中,这些信号都被定义为正整数。没有信号为0.。很多条件可以产生一个信号。

1)当用户按某些终端键时,产生信号,在终端上按DELETE键通常产生中断信号(SIGINT)这是停止一个以丢失控制程序的方法,

2)硬件异常产生信号:出书为0、无效的存储访问等等。例如对一个无效存储访问的进程访问一个SIGSEGV

3)进程用kill(2)函数可将信号发送给另一个进程或进程组。

4)用户可用kill(1)命令将信号发送给其他进程,

6)当检测到某种软件条件已经发生,并将其通知有关进程时也产生信号。例如SIGURG(在网络连接上传来非规定波特率的数据)、SIGPIPR(在管道的读进程已终止后一个进程写此管道),以及SIGALARM(进程所设置的闹钟时间已经超时)

信号时异步时间的经典实例。产生信号的事件对进程而言是随机出现的,进程不能只是测试一个变量来判断是否发生了一个信号,而是必须告诉内核“在此信号发生时,请执行下述操作”可以要求系统在某个信号出现时按照下列三种方式中的一种执行操作:

1)忽略此信号

2)捕获此信号

3)执行默认操作

SIGARBT 调用abort函数时产生此信号。进程异常终止

SIGALRM 超过用alarm函数设置的时间时产生此信号

SIGBUS 指示一个实现定义的硬件故障

SIGCHLD 如果父进程希望了解其子进程的这种状态改变,则应捕获此信号。信号捕捉函数中通常要调用wait函数以取得子进程ID和其终止状态

SIGFPE 此信号标志一个算术运算异常。

SIGHUP 如果终端界面检测到一个连接断开,则将此信号送给与该终端相关的控制进程。

SIGINT 当用户按中断键,终端驱动程序产生此信号兵送至前台进程组中的每一个进程。当一个进程在运行时失控,特别是它正在屏幕上产生大量不需要的输出时,常用词信号终止它。

SIGPIPE 如果在读进程已终止时写管道,则产生此信号。

三、signal函数

UNIX信号机制最简单的界面是signal函数

#include <signal.h>

void (*signal(int signo,void(*func(int))))(int);

signo参数是信号名。func的值是:1)常熟SIG_IGN 2)常熟SIG_DFL 3)当接到此信号后要调用的函数的地址。如果指定SIG_IFN,则向内核表示忽略此信号,如果指定SIG_DFL,则表示接到此信号后的动作时系统默认操作。当指定函数地址时,我们乘此为捕获此信号。我们称此函数为信号处理程序或信号捕获函数。signal函数的原型说明此函数要求两个参数,返回一个函数指针,而该指针所指向的函数五返回值(void).第一个参数signo是一个整形数,第二个参数是函数指针,它所指向的函数需要一个整形参数,五返回值。用一般语言来描述也就是要向信号处理程序传送一个整形参数,而它却无返回值。当调用signal设置信号处理程序时,第二个参数是指向该函数(也就是信号处理程序)的指针。signal的返回值则是指向以前的信号处理程序的指针。



四、不可靠的信号

在早期的版本中有些信号是不可靠地

五、中断的系统调用

早期的UNIX系统的一个特性是:如果在进程执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行。该系统调用返回出错,其ERRNO设置为EINTR。这样处理的理由是,因为一个信号发生了,进程捕捉到了它,这意味着已经发生了某种事情,所以是个好机会应该唤醒则是的系统调用。在这里,我们必须区分系统调用和函数。当捕获到某个信号时,被中断的是内核中执行的系统调用。为了支持这种特性,将系统调用分成两类:低俗系统刁艳红和其他系统调用。低速系统调用是可能会使进程永远阻塞的一类系统调用,包括:

1)在读某些类型的文件时,如果数据并不存在则可能会使调用者永远阻塞(管道、终端设备以及网络设备)

2)在写这些类型的文件时,如果不能立即接受这些数据,则也可能会使调用者永远阻塞

3)打开文件,在某种条件发生之前也可能会使调用者阻塞

4)某种ioctl操作

5)某些进程间通信函数

可以用中断系统调用这种方法来处理的一种情况是:一个进程启动了读终端操作,而使用该终端设备的用户却离开该终端很长时间,与被中断的系统调用相关的问题是必需显示方法处理出错返回。典型的代码序列(一个读操作,被中断,重启)可能如下列样式:

again:
       if((n=read(fd,buff,BUFFSIEZE))<0){
            IF(ERRNO==eintr)
               goto again;

         }


为了帮助应用程序使其不必处理被终端的系统调用,某些被中断的系统调用的自动再启动。自动再启动的系统调用包括:ioctl、read readv write writev wait和waitpid。其中前五个函数只有对低俗设备进行操作时才会被信号中断。而wait和waitpid在捕获大信号时总是被中断。.

六、可重如函数

进程捕获到信号兵继续执行时,它首先执行该信号处理程序中的指令。如果从信号处理程序返回(假如没有exit或longjmp),则继续执行在捕获到信号时进程正在执行的正常指令徐磊(类似于硬件中断发生时所做的)。但在信号处理程序中,不能判断捕获到信号时进程执行到何处。

七、SIGCLD信号

这个函数是不同版本系统下的不同表示方法

八、可靠信号属于和语义

当造成信号的事件发生时,为进程产生一个信号(或向一个进程发送一个信号)。事件可以是硬件异常、软件条件(例如闹钟时间超过)、终端产生的信号或调用kill函数。在产生了信号时,内核通常在进程表中设置某种形式的一个标志。当对信号做了这种动作时,我们说向一个进程递送了一个信号。

进程可以选用“信号递送阻塞”。如果为进程产生了一个选择为阻塞的信号,而且对该信号的动作时系统默认动作或捕获该信号,则为该进程将此信号保持为未决状态,直到该进程对此信号解除了阻塞,或者将此信号的动作更改为忽略,

九、kill和raise函数

kill函数将信号发送给进程或进程组。raise函数则运行进程向自身发送信号。

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid,int signo);

int raise(int signo);

kill的pid参数有四种不同的情况:

pid>0 将信号发送给进程ID为pid的进程

pid==0 将信号发送给其进程组ID等于放进程的进程组ID,而且发送进程有许可权向其发送信号的所有 进程

pid<0 将信号发送给其进程组ID等于PID绝对值,而且发送进程有许可权向其发送信号的所有进程



十、alarm和pause函数

每个进程只能有一个闹钟时间。如果在调用alarm时,以前已为该进程设置过闹钟时间,而且它还没有超时,则该闹钟时间的余留值作为本溪alarm函数的值返回,以前等级的闹钟时间则被新值代换

如果有以前等级的尚未超过的闹钟时间,而且seconds值是0,则取消以前的闹钟时间,其余留值仍为函数的返回值。

pause函数使调用进程挂起直至捕获到一个信号。

只有执行了一个信号处理程序并从其返回时,pause才返回。在这种情况下,pause返回-1,errno设置为EINTR.

十一、信号集

十二、sigprocmask函数

十三、sigpending函数

十四、sigaction函数

十五、sigsetjmp和sigionjmp函数

十六、sigsuspend函数

此函数的功能是检查或修改与指定信号箱关联的处理动作。

十七、abort函数

十八、system函数

十九、sleep函数

二十、作业控制函数

二十一、其他特征

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: