下面代码第一版的文件,第二版的文件在 lib/tellwait.c中,不用再单独下载。
默认是以信号量方式实现,但在Freebsd 9下面运行效果并不理想。参考资料2中有按管道方式实现。将 "ourhdr.h" 修改为 "apue.h"。
FreeBSD 下
命令获取
fetch http://www.yendor.com/programming/unix/apue/lib.44/tellwait.c
tellwait.c
#include <signal.h>
#include "apue.h"static volatile sig_atomic_t sigflag;/* set nonzero by signal handler */
static sigset_t newmask, oldmask, zeromask;static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{sigflag = 1;return;
}void
TELL_WAIT()
{if (signal(SIGUSR1, sig_usr) == SIG_ERR)err_sys("signal(SIGINT) error");if (signal(SIGUSR2, sig_usr) == SIG_ERR)err_sys("signal(SIGQUIT) 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");
}
SVR4 和SunOS下
命令获取命令
fetch http://www.yendor.com/programming/unix/apue/lib.svr4/tellwait.c
tellwait.c
#include <signal.h>
#include "apue.h"static volatile sig_atomic_t sigflag;/* set nonzero by signal handler */
static sigset_t newmask, oldmask, zeromask;static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{sigflag = 1;return;
}void
TELL_WAIT()
{if (signal(SIGUSR1, sig_usr) == SIG_ERR)err_sys("signal(SIGINT) error");if (signal(SIGUSR2, sig_usr) == SIG_ERR)err_sys("signal(SIGQUIT) 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");
}
将下载后的tellwait.c(或者apue源文件包中的 /lib/tellwait.c)拷贝至/usr/include,然后在源文件中将tellwait.c包含即可编译。
#include "tellwait.c"
参考资料:
[1]Chapter 8 Process Control.http://www.yendor.com/programming/unix/apue/ch8.html
[2]APUE 中的TELL函数.http://blog.csdn.net/born1985man/article/details/4635778
[3]《UNIX环境高级编程》程序清单8-7编译错误:TELL_WAIT, WAIT_PARENT, TELL_CHILD未定义.http://blog.csdn.net/fushaobing2010/article/details/6160204