sigsuspend的理解

    xiaoxiao2022-06-22  21

    sigsuspend的核心目标是使进程suspend,那么suspend之后如何唤醒进程,借助的手段是“信号”,进程中”任何“信号的” 接收“都会使得suspend醒来, 注意此处用的词是”接收“,也即进程信号屏蔽字中的信号投递是不可能唤醒suspend的,那么如果想用这些信号唤醒该怎么办呢,我们可以使用 sigsuspend的参数实现,该参数也是信号屏蔽字,只不过该屏蔽字仅仅在sigsuspend函数 执行期间起作用,因此我们可以在该参数屏蔽字中把进程 信号屏蔽字中屏蔽的信号去掉,这样,进程就可以接收到这些信号从而唤醒suspend了。 #include "apue.h" static void sig_int(int); int main(void) {     sigset_t newmask, oldmask, waitmask;     pr_mask("program start: ");     if (signal(SIGINT, sig_int) == SIG_ERR)     err_sys("signal(SIGINT) error");     sigemptyset(&waitmask);     /*     * 添加SIGUSR1,SIGUSR1 本身对实现本程序的功能并无意义,仅仅是为了说明sigsuspend在执行前、执行中、执行后三种状态下进程信号屏蔽字的异同,     * 为了说明sigsuspend会自动恢复进程信号屏蔽字。     */     sigaddset(&waitmask, SIGUSR1);     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: ");     /*     * Pause, allowing all signals except SIGUSR1.     */     if (sigsuspend(&waitmask) != -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 ...     */     pr_mask("program exit: ");     exit(0); } static void sig_int(int signo) {     pr_mask("\nin sig_int: "); } +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #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"); } 使用示例: #include "apue.h" /* 注意为什么子进程不需要调用TELL_WAIT,因为父进程fork的子进程,子进程会 继承父进程的信号屏蔽字 */ TELL_WAIT(); /* set things up for TELL_xxx & WAIT_xxx */ if ((pid = fork()) < 0) {     err_sys("fork error"); } else if (pid == 0) { /* child */     /* child does whatever is necessary ... */     TELL_PARENT(getppid()); /* tell parent we’re done */     WAIT_PARENT(); /* and wait for parent */     /* and the child continues on its way ... */     exit(0); } /* parent does whatever is necessary ... */ TELL_CHILD(pid); /* tell child we’re done */ WAIT_CHILD(); /* and wait for child */ /* and the parent continues on its way ... */ exit(0);
    转载请注明原文地址: https://ju.6miu.com/read-1122776.html

    最新回复(0)