zoukankan      html  css  js  c++  java
  • 【C】——利用sigsuspend函数等待信号阻塞进程

    1 #include<signal.h>
    2 int sigsuspend(const sigset_t *sigmask);
    3             返回值:-1,并将errno设置为EINTR

      将进程的信号屏蔽字设置为由sigmask指向的值,在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。

    例子:

      利用sigsuspend函数阻塞子进程;

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<signal.h>
     4 #include<unistd.h>
     5 
     6 sig_atomic_t sigflag;
     7 sigset_t newmask,oldmask,zeromask;
     8 
     9 void sig_int(int signo)
    10 {
    11     sigflag = 1;
    12 }
    13 
    14 void tell_wait(void)
    15 {
    16     sigflag = 0;
    17     if(signal(SIGUSR1,sig_int) == SIG_ERR){
    18         printf("signal error!
    ");
    19         exit(1);
    20     }
    21     printf("after signal!
    ");
    22 /*    
    23     sigemptyset(&newmask);
    24     sigemptyset(&zeromask);
    25     sigaddset(&newmask,SIGINT);
    26     if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0){
    27         printf("sigprocmask error!
    ");
    28         exit(1);
    29     }
    30 */
    31 }
    32 
    33 void tell_child(pid_t pid)
    34 {
    35     kill(pid,SIGUSR1);
    36 }
    37 
    38 void wait_parent(void)
    39 {
    40     while(sigflag == 0)
    41         sigsuspend(&zeromask);
    42         
    43     sigflag = 0;
    44 
    45     if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){
    46         printf("sigprocmask erro!
    ");
    47         exit(1);
    48     }
    49 }
    50 
    51 int main(int argc, char *argv[])
    52 {
    53     pid_t pid;
    54 
    55     printf("before signal!
    ");
    56 
    57     tell_wait();
    58 
    59     if((pid = fork()) < 0){
    60         printf("fork error!
    ");
    61         exit(1);
    62     }
    63     else if(pid == 0){
    64         wait_parent();
    65         printf("this is child!
    ");
    66         exit(0);
    67     }
    68     else{
    69         printf("this is parent!
    ");
    70         tell_child(pid);
    71     }
    72     exit(0);
    73 }

    例子中的sigprocmask函数是用来检测或更改其信号屏蔽字,或者在一个步骤中同时执行这两个操作。

    #include<signal.h>
    
    int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
                          //返回值:成功返回0,出错返回-1

    how: SIG_BLOCK   SIG_UNBLOCK   SIG_SETMASK

    sigprocmask配合sigpending函数使用,

    #include<signal.h>
    
    int sigpending(sigset_t *set);
                //返回值:成功返回0,出错返回-1

    sigpending函数:查询被搁置的信号!

    其实sigsuspend是一个原子操作,包含4个步骤:

    (1) 设置新的mask阻塞当前进程;
    (2) 收到信号,恢复原先mask;
    (3) 调用该进程设置的信号处理函数;
    (4) 待信号处理函数返回后,sigsuspend返回。

    pause函数和sigsuspend函数的区别:

    简单的说, sigsuspend = unblock + pause     
    sigsuspend 函数是用于需要先接触 某个信号的阻塞状态 然后等待该信号发生 这样的应用场景; 而使用 pause 在达到这样的效果时肯定是需要先 调用sigprocmask进行取消阻塞,再调用pause去等待,取消阻塞与等待两步之间有时间窗口,在信号发生在调用pause之前任意时刻的话都有可能导致pause之后再也收不到该信号,也就是永远休眠。为了解决这种情况,sigsuspend函数把这两步做成一个原子操作,这就保证不会丢失(错过)信号,也就不会发生永远休眠这种情况(根本不发生该信号时除外)。所以,建议只用sigsuspend去等待信号。
  • 相关阅读:
    岛田庄司《占星术杀人魔法》读后感
    OutputCache祥解
    ZOJ Monthly, June 2014 月赛BCDEFGH题题解
    接口和抽象类有什么差别
    C语言指针的初始化和赋值
    深入探讨this指针
    郁 繁体为“鬰” 古同 “鬱”
    socketpair的使用
    Android的FrameLayout使用要注意的问题
    下确界和上确界
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/3380865.html
Copyright © 2011-2022 走看看