zoukankan      html  css  js  c++  java
  • 函数函数sigaction、signal

    函数函数sigaction

    1. 函数sigaction原型:

    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

    分析:

    • 参数 signum :要捕获的信号。
    • 参数act:truct sigaction 结构体,后面具体讲解传入参数,新的处理方式
    • 参数oldact:返回旧的 struct sigaction 结构体,传出参数,旧的处理方式

    1.2 struct sigaction 结构体

    1 struct sigaction
    2 {
    3     void(*sa_handler)(int);
    4     void(*sa_sigaction)(int, siginfo_t *, void *);
    5     sigset_t sa_mask;
    6     int sa_flags;
    7     void(*sa_restorer)(void);
    8 };

    分析:

    • sa_handler : 不带附加参数的信号处理函数指针
    • sa_sigaction: 带有附加参数的信号处理函数指针(两个信号处理函数指针只能二选一)
    • sa_mask: 在执行信号处理函数时,应该屏蔽掉哪些信号
    • sa_flags: 用于控制信号行为,它的值可以是下面选项的组合。
    • SA_SIGINFO:如果指定该选项,则向信号处理函数传递参数(这时应该使用 sa_sigaction 成员而不是 sa_handler).
    • sa_restorer:该成员在早期是用来清理函数栈的,如今已被废弃不用。

    注意:sa_flags 的选项比较多,大部分可又自己做实验验证,有些是需要额外的知识,比如 SA_ONESTACK 和 SA_RESTART,这些放到后面讲解。本节示例中,只需要把 sa_flags 设置为 0 即可。

    信号捕捉特性:

    • 进程正常运行时,默认PCB有一个信号屏蔽字,假定为☆,它决定了进程自动屏蔽哪些信号,当注册了某个信号步捕捉函数,捕捉到该信号以后,要调用该函数,而该函数有可能执行很长时间,在这期间所屏蔽的信号不由☆指定,而由sa_mask来指定,调用完信号处理函数,再恢复为☆。
    • xxx信号捕捉函数执行期间,XXX信号自动屏蔽。
    • 阻塞的常规信号不支持排队,产生多次只记录一次(后32个实时信号支持排队)

    1. 测试代码:

     1 #include<stdio.h>
     2 #include<signal.h>
     3 #include<stdlib.h>
     4 #include<unistd.h>
     5  
     6 void docatch(int signo)
     7 {
     8     printf("%d signal is catch
    ", signo);
     9 }
    10  
    11 int main()
    12 {
    13     int ret;
    14     struct sigaction act;
    15     act.sa_handler = docatch;
    16     sigemptyset(&act.sa_mask);
    17     sigaddset(&act.sa_mask, SIGQUIT);
    18     act.sa_flags = 0;  //默认属性:信号捕捉函数执行期间,自动屏蔽本信号
    19     ret = sigaction(SIGINT, &act, NULL);
    20     if(ret < 0) 
    21     {
    22         perror("sigaction error");
    23         exit(1);
    24     }
    25     while(1)
    26       sleep(1);
    27     return 0;
    28 }

    输出结果:

     2. 测试代码:

     1 #include<stdio.h>
     2 #include<signal.h>
     3 #include<stdlib.h>
     4 #include<unistd.h>
     5  
     6 void docatch(int signo)
     7 {
     8     printf("%d signal is catch
    ", signo);
     9     sleep(10);
    10     printf("--------------finish-
    ");
    11 }
    12  
    13 int main()
    14 {
    15     int ret;
    16     struct sigaction act;
    17     act.sa_handler = docatch;
    18     sigemptyset(&act.sa_mask);
    19     sigaddset(&act.sa_mask, SIGQUIT);
    20     act.sa_flags = 0;  
    21     ret = sigaction(SIGINT, &act, NULL);
    22     if (ret < 0) 
    23     {
    24         perror("sigaction error");
    25         exit(1);
    26     }
    27     while (1)
    28         sleep(1);
    29     return 0;
    30 }

    输出结果:

    3. 测试代码:

     1 #include <unistd.h>
     2 #include <signal.h>
     3 #include <stdio.h>
     4 
     5 void printsigset(const sigset_t *set)
     6 {
     7     for (int i = 1; i <= 64; i++)
     8     {
     9         if (i == 33) putchar(' ');
    10         if (sigismember(set, i) == 1)
    11             putchar('1');
    12         else
    13             putchar('0');
    14     }
    15     puts("");
    16 }
    17 
    18 void handler(int sig)
    19 {
    20     if (sig == SIGTSTP) 
    21         printf("hello SIGTSTP
    ");
    22     if (sig == SIGINT) 
    23         printf("hello SIGINT
    ");
    24     sleep(5);
    25     sigset_t st;
    26     sigpending(&st);
    27     printsigset(&st);
    28 }
    29 
    30 int main()
    31 {
    32     printf("I'm %d
    ", getpid());
    33     struct sigaction act, oldact;
    34     act.sa_handler = handler;   // 设置普通信号处理函数                     
    35     sigemptyset(&act.sa_mask);  // 向 sa_mask 中添加 SIGINT
    36     sigaddset(&act.sa_mask, SIGINT);
    37     act.sa_flags = 0; // 先置 0
    38 
    39     sigaction(SIGTSTP, &act, &oldact);
    40     sigaction(SIGINT, &act, &oldact);
    41 
    42     while (1) 
    43     {
    44         write(STDOUT_FILENO, ".", 1);
    45         pause();
    46     }
    47     return 0;
    48 }

    输出结果:

    分析:

    • 当程序运行的时候,Ctrl C 进入 handler,然后立即 Ctrl Z 发现 handler 还未执行完就被 SIGTSTP 打断.
    • 当程序运行的时候,Ctrl Z 进入 handler,然后立即 Ctrl C 发现并不会被 SIGINT 打断,这是因为该 handler 注册的时候被设置了 SA_MASK = SIGINT。最后 handler 结束的时候打印了未决信号集,发现里头有 SIGINT。所以 handler 结束后,又去继续对 SIGINT 进行处理。
  • 相关阅读:
    最大子数组求和并进行条件组合覆盖测试
    Ubuntu 16.04 c++ Google框架单元测试
    The directory '/home/stone/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If execu
    Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    个人博客作业三:微软小娜APP的案例分析
    补交 作业一
    补交 作业二:个人博客作业内容:需求分析
    嵌入式软件设计第12次实验报告
    嵌入式软件设计第11次实验报告
    嵌入式软件设计第10次实验报告
  • 原文地址:https://www.cnblogs.com/sunbines/p/10265659.html
Copyright © 2011-2022 走看看