apue 2e TELL_WAIT TELL_PARENT WAIT_PARENT TELL_CHILD WAIT_CHILD 實現

下面代碼第一版的文件,第二版的文件在 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章