unp-----signal函数与系统中断

来源:互联网 发布:淘宝药店 编辑:程序博客网 时间:2024/05/22 15:39

一.signal分析

在POSIX中信号的处理:

#include  void (*signal(int signo, void (*func)(int)))(int) {      struct sigaction act, oact;      act.sa_handler = func; // siaction结构的sa_handler成员位置为函数func      sigemptyset(&act.sa_mask); //该信号集设置为空集。代表在该信号处理函数不堵塞任何信号。POSIX保证被捕捉的信号在其信号处理函数运行期间总是堵塞      act.sa_flags = 0;      if(signo == SIGALRM){ //此操作增加的函数的可移植性 #if SA_INTERRUPT       act.sa_flags |= SA_INTERRUPT;  //SunOS 4.x  #end if  }else{ #if SA_RESTART   act.sa_flags |= SA_RESTART;  //SVR4, 4.4BSD #end if   }        if(sigaction(signo, &act, &oact)< 0)        //struct sigaction{                                                      //   void(*sa_handler)(int);                                                       //  sigset_t sa_mask;                                                       //  int sa_flags;                                                       //  void(*sa_sigaction)(int, siginfo_t, void *);                                                          //  };signo代表是要检测或者修改具体信号的动作编号。    return SIG_ERR;         return oact.sa_handler; }

1)一旦安装了该信号,他便会一直安装着

2)在一个信号处理函数运行期间,正在被递交的函数是堵塞的。而且,传递给函数sigaction中的第二个参数不为空的时候,假设第二个参数为struct sigaction act,那么act.sa_mask信号集中指定的任何额外信号都会被堵塞。

3)如果一个信号在被堵塞期间产生了一次或者多次,那么该信号只提交一次(也就是unix信号不排队处理)。

4)我们可以利用sigprocmask函数选择性地堵塞或解除一组信号的堵塞0


具体例如如下:

#include  #include  #include  #include  using namespace std;  void sig_deal(int signo) {         char ch;         cout << "deal the signal finished\n"; }  int main() {         struct sigaction act,oact;         act.sa_handler = sig_deal;//    sigaction(SIGALRM, &act, &oact);    act.sa_flags = SA_RESTART      alarm(1);       char ch;         scanf(" %c", &ch);          alarm(1);         scanf(" %c", &ch);          return 0; }


该例子证明了POSIX信号处理的第一条性质:1)一旦安装了该信号,他便会一直安装着

二.系统中断

低速系统调(慢系统)用(Slow system call)该术语适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用是指调用永远无法返回,多数网络支持函数都属于这一类。如:若没有客户连接到服务器上,那么服务器的accept调用就会一直阻塞。慢系统调用可以被永久阻塞,包括以下几个类别:(1)读写‘慢’设备(包括pipe,终端设备,网络连接等)。读时,数据不存在,需要等待;写时,缓冲区满或其他原因,需要等待。读写磁盘文件一般不会阻塞。(2)当打开某些特殊文件时,需要等待某些条件,才能打开。例如:打开中断设备时,需要等到连接设备的modem响应才能完成。(3)pause和wait函数。pause函数使调用进程睡眠,直到捕获到一个信号。wait等待子进程终止。(4)某些ioctl操作。(5)某些IPC操作。

系统调用的定义:当一个进程调用而堵塞的时候,由于捕获到某个信号,而中断了该进程的系统调用,系统调用的函数返回出错,errno = EINTR

例子:

第二段代码的因为SIGALRM中断了系统调用scanf

修改方案1:如果在上诉程序中加入此代码(act.sa_flags = SA_RESTART;),那么就会出现被中断的系统调用(scanf)将会重新被调用

该方案缺点:因为考虑所有代码在不同系统上面的可移植性,该处理方案在不支持SA_RESTART系统上无效

在centos6.5系统上运行结果如下:

在《unix网络编程》这本书上面,5.9节将会还有对此系统中断处理的例子

 
原创粉丝点击