• APUE 学习笔记(七) 信号


    1.信号是软件中断,提供一种异步处理事件的方法

    很多事件产生信号:
    (1)用户按下某些中断键,如 Ctrl + C键产生 SIGINT信号
    (2)硬件异常产生信号,比如 除数为0,无效的内存引用 
    (3)进程调用kill函数可将信号发送给另一个进程
     
    处理信号的三种方式:
    (1)忽略此信号。大多数信号都采用这种方式处理,但是 SIGKILL和SIGSTOP决不能忽略
    (2)捕捉信号。发生某种信号时,调用一个信号处理函数。SIGKILL和SIGSTOP信号不能被捕捉
    (3)执行系统默认动作。大多数是终止进程
     
    SIGCHLD:进程终止时向其父进程发送的信号,默认为忽略。父进程也可以捕捉该信号。
    SIGFPE:  算术运算异常,如除数为0
    SIGINT:  用户按下中断键,一般为 Ctrl + C
    SIGSEGV:无效的内存引用
     

    2.中断的系统调用

    如果进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就中断不再执行
    低速系统调用:读写某些类型文件(管道、终端、网络套接字)
     
    again:
         if ((n = read(fd, buf, BUFSIZE)) < 0) {
             if (errno == EINTR)
                 goto again;              /* just an interrupted system call */
             /* handle other errors */
    }

    3.使用longjmp,带超时限制调用read

      #include <stdio.h>
      #include <setjmp.h>
      #include <unistd.h>
      #include <signal.h>
      
      static jmp_buf env_alarm;
      static void sig_alarm(int signo)
      {
          longjmp(env_alarm, 1);
      }
      
    int main(int argc, char* argv[])
      {
          char buf[4096];
          if (signal(SIGALRM, sig_alarm) == SIG_ERR) {
              fprintf(stderr, "signal(SIGALRM) error
    ");
          } 
      
          if (setjmp(env_alarm) != 0) {
              fprintf(stderr, "read timeout
    ");
              return -1;
          } 
          alarm(5);
          int nread = 0;
          if ((nread = read(STDIN_FILENO, buf, 4096)) < 0) {
              fprintf(stderr, "read error
    ");
          } 
          alarm(0);
          write(STDOUT_FILENO, buf, nread);
          return 0;
      }

    4.sigaction函数

    sigaction函数用来检查或修改与指定信号相关联的处理动作
    struct sigaction {
        void       (*sa_handler)(int);       /* addr of signal handler */
        sigset_t   sa_mask;                  /*  addtional signals to block */
        int        sa_flags;                 /*  signal options */
        void       (*sa_sigaction)(int, siginfo_t *, void *);     /* alternate handler */
    };

    posix使用sigaction实现signal(原有的signal函数语义不可靠)

    typedef void Sigfunc(int);
    
    Sigfunc* signal(int signo, Sigfunc* func)
    {
        struct sigaction newact, oldact;
        newact.sa_handler = func;
        sigemptyset(&newact.sa_mask);
        newact.sa_flags = 0;
        if (signo == SIGALRM) {
    #ifdef SA_INTERRUPT
            newact.sa_flags |= SA_INTERRUPT;
    #endif
        } else {
    #ifdef SA_RESTART
            newact.sa_flags |= SA_RESTART;
    #endif
        }   
        if (sigaction(signo, &newact, &oldact) < 0) {
            return (SIG_ERR);
        }   
        return oldact.sa_handler;
    }
  • 相关阅读:
    版本控制工具 svn 一
    测试用例 (一)
    Jmeter (四) 关联
    Jmeter (三) 集合点 、检查点 (断言)
    Jmeter (二) 参数化
    Jmeter (一) 安装
    自动化测试 selenium 测试软件安装
    postman 接口测试(一)
    PHP使用Redis的Pub/Sub(发布订阅)命令
    idea控制台乱码问题
  • 原文地址:https://www.cnblogs.com/wwwjieo0/p/3716617.html
Copyright © 2020-2023  润新知