进程控制(二)

5 wait和waitpid函数

  当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。

5.1调用wait或waitpid的进程可能会:

    阻塞(如果其子进程都还在运行)

    带子进程的终止状态立即返回

    出错立即返回

5.2wait和waitpid的区别: 

    在一个子进程终止前, wait 使其调用者阻塞,而 waitpid 有一选择项,可使调用者不阻塞。

    waitpid并不等待第一个终止的子进程—它有若干个选择项,可以控制它所等待的进程。

 

代码示例:

#include "ourhdr.h"
#include <sys/wait.h>

void pr_exit(int status)
{
	if (WIFEXITED(status))
		printf("normal termination, exit status = %d\n",
				WEXITSTATUS(status));
	else if (WIFSIGNALED(status))
		printf("abnormal termination, signal number = %d%s\n",
				WTERMSIG(status),
#ifdef	WCOREDUMP
				WCOREDUMP(status) ? " (core file generated)" : "");
#else
				"");
#endif
	else if (WIFSTOPPED(status))
		printf("child stopped, signal number = %d\n",
				WSTOPSIG(status));
}

int main(void)
{
	pid_t	pid;
	int		status;

	if ((pid = fork()) < 0)
		err_sys("fork error");
	else if (pid == 0)				/* child */
		exit(7);

	if (wait(&status) != pid)		/* wait for child */
		err_sys("wait error");
	pr_exit(status);				/* and print its status */

	if ((pid = fork()) < 0)
		err_sys("fork error");
	else if (pid == 0)				/* child */
		abort();					/* generates SIGABRT */

	if (wait(&status) != pid)		/* wait for child */
		err_sys("wait error");
	pr_exit(status);				/* and print its status */

	if ((pid = fork()) < 0)
		err_sys("fork error");
	else if (pid == 0)				/* child */
		status /= 0;				/* divide by 0 generates SIGFPE */

	if (wait(&status) != pid)		/* wait for child */
		err_sys("wait error");
	pr_exit(status);				/* and print its status */

	exit(0);
}

  打印结果:

[root@rac1 fork]# gcc wait.c 
wait.c: In function ‘main’:
wait.c:48: warning: division by zero

[root@rac1 fork]# ./a.out 
normal termination, exit status = 7
abnormal termination, signal number = 6
abnormal termination, signal number = 8

 5.3如果一个进程要 f o r k一个子进程,但不要求它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的诀窍是调用 f o r k两次。

代码示例:

#include "ourhdr.h"
#include <sys/wait.h>
#include <sys/types.h>

int
main(void)
{
	pid_t	pid;

	if ((pid = fork()) < 0) {
		err_sys("fork error");
	} else if (pid == 0) {		/* first child */
		if ((pid = fork()) < 0)
			err_sys("fork error");
		else if (pid > 0)
			exit(0);	/* parent from second fork == first child */

		/*
		 * We‘re the second child; our parent becomes init as soon
		 * as our real parent calls exit() in the statement above.
		 * Here‘s where we‘d continue executing, knowing that when
		 * we‘re done, init will reap our status.
		 */
		sleep(2);
		printf("second child, parent pid = %d\n", getppid());
		exit(0);
	}

	if (waitpid(pid, NULL, 0) != pid)	/* wait for first child */
		err_sys("waitpid error");

	/*
	 * We‘re the parent (the original process); we continue executing,
	 * knowing that we‘re not the parent of the second child.
	 */
	exit(0);
}

  

 打印结果:

[root@rac1 fork]# ./a.out 
[root@rac1 fork]# second child, parent pid = 1

  

6 wait3 和wait4函数

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。