• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Linux被中断的系统如何调用详解

    前言

    慢系统调用,指的是可能永远无法返回,从而使进程永远阻塞的系统调用,比如无客户连接时的accept、无输入时的read都属于慢速系统调用。

    在Linux中,当阻塞于某个慢系统调用的进程捕获一个信号,则该系统调用就会被中断,转而执行信号处理函数,这就是被中断的系统调用。

    然而,当信号处理函数返回时,有可能发生以下的情况:

    下面我们编写代码,分别验证上述几种情形,其中系统调用选择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;
    }


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

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

    总结

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

    上一篇:Docker 容器操作指令汇总详解
    下一篇:利用Dockerfile部署SpringBoot项目的方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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