好贷网好贷款

信号实现父子进程之间的同步--sigsuspend的作用

发布时间:2016-12-5 10:32:55 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"信号实现父子进程之间的同步--sigsuspend的作用",主要涉及到信号实现父子进程之间的同步--sigsuspend的作用方面的内容,对于信号实现父子进程之间的同步--sigsuspend的作用感兴趣的同学可以参考一下。

函数原型:   #include <signal.h>   int sigsuspend(const sigset_t *mask); 作用:   用于在接收到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。   也就是说,sigsuspend后,进程就挂在那里,等待着开放的信号的唤醒。系统在接收到信号后,马上就把现在的信号集还原为原来的,然后调用处理函数。 返回值:   sigsuspend返回后将恢复调用之前的的信号掩码。信号处理函数完成后,进程将继续执行。该系统调用始终返回-1,并将errno设置为EINTR.   Since sigsuspend() suspends process execution indefinitely, there is no successful completion return value. If a return occurs, -1 is returned and errno is set to indicate the error.   The sigsuspend() function will fail if:   [EINTR]   A signal is caught by the calling process and control is returned from the signal-catching function. 也就是说,sigsuspend后,进程就挂在那里,等待着开放的信号的唤醒。系统在接受到信号后,马上就把现在的信号集还原为原来的,然后调用处理函数。 Stevens在《Unix环境高级编程》一书中是如是回答的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由于sigsuspend是原子操作,所以这句给人的感觉就是先调用signal handler先返回,然后sigsuspend再返回。 [cpp] view plaincopyprint? int main(void) {        sigset_t   newmask, oldmask, zeromask;             if (signal(SIGINT, sig_int) == SIG_ERR)           err_sys("signal(SIGINT) error");             sigemptyset(&zeromask);             sigemptyset(&newmask);        sigaddset(&newmask, SIGINT);        /* block SIGINT and save current signal mask */        if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)           err_sys("SIG_BLOCK error");             /* critical region of code */        pr_mask("in critical region: ");             /* allow all signals and pause */        if (sigsuspend(&zeromask) != -1)           err_sys("sigsuspend error");        pr_mask("after return from sigsuspend: ");             /* reset signal mask which unblocks SIGINT */        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)           err_sys("SIG_SETMASK error");             /* and continue processing ... */        exit(0);     }          static void sig_int(int signo) {        pr_mask("\nin sig_int: ");        return;     }     结果: [cpp] view plaincopyprint? $a.out     in critical region: SIGINT     ^C     in sig_int: SIGINT     after return from sigsuspend: SIGINT     如果按照sig_handler先返回,那么SIGINT是不该被打印出来的,因为那时屏蔽字还没有恢复,所有信号都是不阻塞的。那么是Stevens说错了么?当然没有,只是Stevens没有说请在sigsuspend的原子操作中到底做了什么? sigsuspend的整个原子操作过程为: (1) 设置新的mask阻塞当前进程; (2) 收到信号,恢复原先mask; (3) 调用该进程设置的信号处理函数; (4) 待信号处理函数返回后,sigsuspend返回。 [cpp] view plaincopyprint? #include <stdio.h>     #include <signal.h>          void checkset();     void func();     void main()     {          sigset_tblockset,oldblockset,zeroset,pendmask;          printf("pid:%ld\n",(long)getpid());          signal(SIGINT,func);               sigemptyset(&blockset);          sigemptyset(&zeroset);          sigaddset(&blockset,SIGINT);               sigprocmask(SIG_SETMASK,&blockset,&oldblockset);          checkset();          sigpending(&pendmask);               if(sigismember(&pendmask,SIGINT))              printf("SIGINTpending\n");               if(sigsuspend(&zeroset)!= -1)          {          printf("sigsuspenderror\n");          exit(0);          }               printf("afterreturn\n");          sigprocmask(SIG_SETMASK,&oldblockset,NULL);               printf("SIGINTunblocked\n");     }          void checkset()     {    sigset_tset;          printf("checksetstart:\n");          if(sigprocmask(0,NULL,&set)<0)          {          printf("checksetsigprocmask error!!\n");          exit(0);          }               if(sigismember(&set,SIGINT))          printf("sigint\n");               if(sigismember(&set,SIGTSTP))          printf("sigtstp\n");               if(sigismember(&set,SIGTERM))          printf("sigterm\n");          printf("checksetend\n");     }          void func()     {          printf("hellofunc\n");     }     父子进程同步到方法如下: [cpp] view plaincopyprint? <span style="font-size:18px;"><strong>#include "apue.h"      static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */   static sigset_t newmask, oldmask, zeromask;      static void   sig_usr(int signo)  /* one signal handler for SIGUSR1 and SIGUSR2 */   {       sigflag = 1;   }      void   TELL_WAIT(void)   {       if (signal(SIGUSR1, sig_usr) == SIG_ERR)           err_sys("signal(SIGUSR1) error");       if (signal(SIGUSR2, sig_usr) == SIG_ERR)           err_sys("signal(SIGUSR2) error");       sigemptyset(&zeromask);       sigemptyset(&newmask);       sigaddset(&newmask, SIGUSR1);       sigaddset(&newmask, SIGUSR2);          /*       * Block SIGUSR1 and SIGUSR2, and save current signal mask.       */       if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)           err_sys("SIG_BLOCK error");   }      void   TELL_PARENT(pid_t pid)   {       kill(pid, SIGUSR2);     /* tell parent we're done */   }      void   WAIT_PARENT(void)   {       while (sigflag == 0)           sigsuspend(&zeromask);  /* and wait for parent */       sigflag = 0;          /*       * Reset signal mask to original value.       */       if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)           err_sys("SIG_SETMASK error");   }      void   TELL_CHILD(pid_t pid)   {       kill(pid, SIGUSR1);         /* tell child we're done */   }      void   WAIT_CHILD(void)   {       while (sigflag == 0)           sigsuspend(&zeromask);  /* and wait for child */       sigflag = 0;          /*       * Reset signal mask to original value.       */       if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)           err_sys("SIG_SETMASK error");   }   </strong></span>  

上一篇:hdu 1164 Eddy's research I
下一篇:移植Linux操作系统时候遇到的问题

相关文章

相关评论