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 进行处理。
  • 相关阅读:
    剑指offer--38.左旋转字符串
    剑指offer--37.和为S的两个数字
    剑指offer--35.数组中只出现一次的数字
    剑指offer--34.数字在排序数组中出现的次数
    剑指offer--33.丑数
    剑指offer--36.整数中1出现的次数(从1到n整数中1出现的次数)
    剑指offer--32.把数组排成最小的数
    剑指offer--31.二叉树中和为某一值的路径
    剑指offer--30.二叉搜索树的后序遍历序列
    剑指offer--29.从上往下打印二叉树
  • 原文地址:https://www.cnblogs.com/sunbines/p/10265659.html
Copyright © 2011-2022 走看看