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

 更新时间:2019年10月12日 08:23:11   作者:原野追逐  
这篇文章主要给大家介绍了关于Linux被中断的系统如何调用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Linux具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

慢系统调用,指的是可能永远无法返回,从而使进程永远阻塞的系统调用,比如无客户连接时的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;
}

alt

使用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;
}

alt

使用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;
}

alt

由于对被中断系统调用处理方式的差异性,因此对应用程序来说,与被中断的系统调用相关的问题是:

  • 应用程序无法保证总是知道信号处理函数的注册方式,以及是否设置了SA_RESTART标志
  • 可移植的代码必须显式处理关键函数的出错返回,当函数出错且errno等于EINTR时,可以根据实际需求进行相应处理,比如重启该函数
int nread = read(fd, buf, 1024);

if (nread < 0)
{
  if (errno == EINTR)
  {
    //read被中断,其实不应该算作失败,可以根据实际需求进行处理,比如重写调用read,也可以忽略它
  }
  else
  {
    //read真正的读错误
  }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对华域联盟的支持。

相关文章

  • LuManager Linux/Unix服务器管理面板推荐之国产面板

    LuManager Linux/Unix服务器管理面板推荐之国产面板

    国外VPS 大多数是 Linux /Unix平台,Linux/Unix平台的优点也很多,重点是它还是免费的,(用过美国VPS 的朋友都知道国外IDC 装Windows是需要版权费的)国内大型网站几乎都是用Linux/Unix平台

    2012-09-09

  • 详解在Linux中怎么使用cron计划任务

    详解在Linux中怎么使用cron计划任务

    本篇文章主要介绍了在Linux中怎么使用cron计划任务,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    2018-03-03

  • CentOS8部署LNMP环境之编译安装mysql8.0.29的教程详解

    CentOS8部署LNMP环境之编译安装mysql8.0.29的教程详解

    这篇文章主要介绍了CentOS8部署LNMP环境之编译安装mysql-8.0.29的教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    2020-04-04

  • Linux seq命令的使用方法

    Linux seq命令的使用方法

    这篇文章主要介绍了Linux seq命令的使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    2020-02-02

  • 修改.htaccess实现子目录绑定示例分享

    修改.htaccess实现子目录绑定示例分享

    这篇文章主要介绍了修改.htaccess实现子目录绑定示例,需要的朋友可以参考下

    2014-03-03

  • PHP程序员玩转Linux系列 自动备份与SVN

    PHP程序员玩转Linux系列 自动备份与SVN

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,学习自动备份与SVN教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    2017-04-04

  • Centos7.3服务器搭建LNMP环境的方法

    Centos7.3服务器搭建LNMP环境的方法

    这篇文章主要介绍了Centos7.3服务器搭建LNMP环境的方法,结合实例形式分析了Centos7.3搭建LNMP环境的相关步骤、命令、使用方法及注意事项,需要的朋友可以参考下

    2018-04-04

  • Ubuntu20.04开启root账户的方法步骤

    Ubuntu20.04开启root账户的方法步骤

    这篇文章主要介绍了Ubuntu20.04开启root账户的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    2020-07-07

  • Linux 服务器同步 Rsync同步服务器文件

    Linux 服务器同步 Rsync同步服务器文件

    服务器之间常常要保持些文件或目录的一致,比如一些大的软件下载网站,它们通常使用多台服
    务器来提供下载服务。

    2009-08-08

  • 详解Linux time 命令的使用

    详解Linux time 命令的使用

    这篇文章主要介绍了详解Linux time 命令的使用,帮助大家更好的理解和学习linux,感兴趣的朋友可以了解下

    2020-08-08

最新评论

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。