UNIX环境高级编程8.9竞争条件
这一节,书中的TELL_WAIT与TELL_PARENT,TELL_CHILD没有弄清楚,到底是如何实现的同步机制。
// proc/tellwait1.c 8-6 #include "apue.h" static void charatatime(const char *); int main(void) { pid_t pid; if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { charatatime("output from child\n"); } else { charatatime("output from parent\n"); } return 0; } static void charatatime(const char* str) { const char* ptr; int c; setbuf(stdout, NULL); /* set unbuffered */ for (ptr = str; (c = *ptr++) != 0; ) { putc(c, stdout); } }
// lib/tellwait.c #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"); }
// proc/tellwait2.c 8-7 #include "apue.h" static void charatatime(const char*); int main() { pid_t pid; TELL_WAIT(); if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { WAIT_PARENT(); /* parent goes first */ charatatime("output from child\n"); } else { charatatime("output from parent\n"); TELL_CHILD(pid); } return 0; } static void charatatime(const char* str) { const char* ptr; int c; setbuf(stdout, NULL); /* set unbuffered */ for (ptr = str; (c = *ptr++) != 0; ) { putc(c, stdout); } }
// proc/tellwait3.c #include "apue.h" static void charatatime(const char*); int main() { pid_t pid; TELL_WAIT(); if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { charatatime("output from child\n"); TELL_PARENT(getppid()); /* parent goes first */ } else { WAIT_CHILD(); charatatime("output from parent\n"); } return 0; } static void charatatime(const char* str) { const char* ptr; int c; setbuf(stdout, NULL); /* set unbuffered */ for (ptr = str; (c = *ptr++) != 0; ) { putc(c, stdout); } }