Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1148552
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2016-09-05 20:28:06

参考原文http://blog.csdn.net/ccccdddxxx/article/details/6308381
信号是异步的,它会在程序的任何地方发生。由此程序正常的执行路径被打破,去执行信号处理函数。
一般情况下
进程正在执行某个系统调用,那么在该系统调用返回前信号是不会被递送的。但慢速系统调用除外,如读写终端、网络、磁盘,以及wait和pause。这些系 统调用都会返回-1,errno置为EINTR当系统调用被中断时,我们可以选择使用循环再次调用,或者设置重新启动该系统调用 (SA_RESTART)。

现在说说对上面话的理解:

我认为函数或进程的运行最终都回归结尾系统调用,(呵呵,非官方,自己理解)

那么 “进程正在执行某个系统调用,那么在该系统调用返回前信号是不会被递送的”,就是说大多数进程在运行期间是阻塞信号的,系统调用完再处理,

但是(以下引用APUE):如果在进程执行一个低速系统而阻塞期间捕捉到一个信号,该系统调用被终端不再继续执行

When a system call is slow and a signal arrives while it was blocked, waiting for something, the call is aborted and returns -EINTR , so that the library function will return -1 and set errno to EINTR . Just before the system call returns, the user program's signal handler is called.

(So, what is "slow"? Mostly those calls that can block forever waiting for external events; read and write to terminal devices, but not read and write to disk devices, wait , pause .)

This means that a system call can return an error while nothing was wrong. Usually one will want to redo the system call. That can be automated by installing the signal handler using a call to sigaction with the SA_RESTART flag set. The effect is that upon an interrupt the system call is aborted, the user program's signal handler is called, and afterwards the system call is restarted from the beginning.

我们可以选择使用循环再次调用,或者设置重新启动该系统调用 (SA_RESTART),

这是是低速系统调用被信号中断的解决办法,1循环2SA——RESTART

好啦,实验代码:

#include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9
 10 void int_handler (int signum)
 11 {
 12         printf ("int handler %d/n",signum);
 13 }
 14
 15 int main(int argc, char **argv)
 16 {
 17         char buf[100];
 18         ssize_t ret;
 19         struct sigaction oldact;
 20         struct sigaction act;
 21
 22         act.sa_handler = int_handler;
 23         act.sa_flags=0;
 24         act.sa_flags |= SA_RESTART;
 25         sigemptyset(&act.sa_mask);
 26         if (-1 == sigaction(SIGINT,&act,&oldact))
 27         {
 28                 printf("sigaction failed!/n");
 29                 return -1;
 30         }
 31
 32         bzero(buf,100);
 33
 34         ret = read(STDIN_FILENO,buf,10);
 35         if (ret == -1)
 36         {
 37                 printf ("read error %s/n", strerror(errn    o));

 38         }
 39         printf ("read %d bytes, content is %s/n",ret,buf    );
 40         sleep (10);
 41         return 0;
 42 }

这里我们就看第二种解决办法SA—restart

运行看结果:

^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
hgfd
read 5 bytes, content is hgfd

^Cint handler 2
在程序read之前不要输入,ctrl+c这样不会中断read输入后主程序就向下运行啦,这样就不在低速的系统调用即read中啦,所以再次ctrl+c结束;

下面改程序:把程序24行注释掉:结果

^Cint handler 2
read error Interrupted system call
read -1 bytes, content is
程序立即结束啦,

但我们和第一次相比也观察到很奇怪的结果

根据结果 比较,其实是第二次运行是把ctrl+c读入,而第一次就是运行啦信号处理函数,不把ctrl+c作为READ的读入,

/////
参考书籍 unix环境高级编程-信号-中断的系统调用

////////

图片

图片

图片

阅读(2340) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~