首页 > 系统 > Linux > 正文

Linux被中断的系统如何调用详解

2024-08-28 00:02:10
字体:
来源:转载
供稿:网友

前言

慢系统调用,指的是可能永远无法返回,从而使进程永远阻塞的系统调用,比如无客户连接时的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;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表