昆仑资源网 Design By www.lawayou.com
前言
慢系统调用,指的是可能永远无法返回,从而使进程永远阻塞的系统调用,比如无客户连接时的accept、无输入时的read都属于慢速系统调用。
在Linux中,当阻塞于某个慢系统调用的进程捕获一个信号,则该系统调用就会被中断,转而执行信号处理函数,这就是被中断的系统调用。
然而,当信号处理函数返回时,有可能发生以下的情况:
- 如果信号处理函数是用signal注册的,系统调用会自动重启,函数不会返回
- 如果信号处理函数是用sigaction注册的
- 默认情况下,系统调用不会自动重启,函数将返回失败,同时errno被置为EINTR
- 只有中断信号的SA_RESTART标志有效时,系统调用才会自动重启
下面我们编写代码,分别验证上述几种情形,其中系统调用选择read,中断信号选择SIGALRM,中断信号由alarm产生。
使用signal
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <errno.h> void handler(int s) { printf("read is interrupt by signal handler\n"); return; } int main() { char buf[10]; int nread = 0; signal(SIGALRM, handler); alarm(2); printf("read start\n"); nread = read(STDIN_FILENO, buf, sizeof(buf)); printf("read return\n"); if ((nread < 0) && (errno == EINTR)) { printf("read return failed, errno is EINTR\n"); } return 0; }
使用sigaction + 默认情况
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <errno.h> void handler(int s) { printf("read is interrupt by signal handler\n"); return; } int main() { char buf[10]; int nread = 0; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_handler = handler; act.sa_flags = 0; //不给SIGALRM信号设置SA_RESTART标志,使用sigaction的默认处理方式 //act.sa_flag |= SA_INTERRUPT; //SA_INTERRUPT是sigaction的默认处理方式,即不自动重启被中断的系统调用 //实际上,不管act.sa_flags值为多少,只要不设置SA_RESTART,sigaction都是按SA_INTERRUPT处理的 sigaction(SIGALRM, &act, NULL); alarm(2); printf("read start\n"); nread = read(STDIN_FILENO, buf, sizeof(buf)); printf("read return\n"); if ((nread < 0) && (errno == EINTR)) { printf("read return failed, errno is EINTR\n"); } return 0; }
使用sigaction + 指定SA_RESTART标志
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <errno.h> void handler(int s) { printf("read is interrupt by signal handler\n"); return; } int main() { char buf[10]; int nread = 0; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_handler = handler; act.sa_flags = 0; act.sa_flags |= SA_RESTART; //给SIGALRM信号设置SA_RESTART标志 sigaction(SIGALRM, &act, NULL); alarm(2); printf("read start\n"); nread = read(STDIN_FILENO, buf, sizeof(buf)); printf("read return\n"); if ((nread < 0) && (errno == EINTR)) { printf("read return failed, errno is EINTR\n"); } return 0; }
由于对被中断系统调用处理方式的差异性,因此对应用程序来说,与被中断的系统调用相关的问题是:
- 应用程序无法保证总是知道信号处理函数的注册方式,以及是否设置了SA_RESTART标志
- 可移植的代码必须显式处理关键函数的出错返回,当函数出错且errno等于EINTR时,可以根据实际需求进行相应处理,比如重启该函数
int nread = read(fd, buf, 1024); if (nread < 0) { if (errno == EINTR) { //read被中断,其实不应该算作失败,可以根据实际需求进行处理,比如重写调用read,也可以忽略它 } else { //read真正的读错误 } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
昆仑资源网 Design By www.lawayou.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
昆仑资源网 Design By www.lawayou.com
暂无评论...
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。