MyException - 我的异常网
当前位置:我的异常网» 人工智能 » wait 跟 waitpid 函数

wait 跟 waitpid 函数

www.MyException.Cn  网友分享于:2013-09-17  浏览:0次
wait 和 waitpid 函数
    当一个进程正常终止或异常终止时,内核就会向其父进程发送 SIGCHLD 信号,父进程对这种信号的默认动作是忽略它。可以使用 wait 和 waitpid 函数来获取子进程的终止状态。
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
                  /* 两个函数返回值:若成功,返回进程 ID;否则,返回 0 或 -1 */

    通常调用这两个函数时:
    * 如果其所有子进程都还在运行,则阻塞。
    * 如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态后立即返回。
    * 如果它没有任何子进程,则立即出错返回。
    这两个函数的区别如下。
    (1)在一个子进程终止前,wait 使其调用者阻塞,而 waitpid 有一选项可使调用者不阻塞。
    (2)waitpid 并不一定要等待在其调用之后的第一个终止子进程,它有若干个可以控制它所等待的进程的选项。
    (3)对于 wait,其唯一的出错是调用进程没有子进程(函数调用被一个信号中断时也可能返回另一种出错)。但对于 waitpid,如果指定的进程或进程组不存在,或者 pid 指定的进程不是调用进程的子进程,都可能出错。
    它们的参数 statloc 如果不是一个空指针,则子进程的终止状态就存放在它所指向的单元内。如果不关心终止状态,则可将其指定为空指针。依照传统,返回的整型状态字是由实现定义的,其中某些位表示退出状态(正常返回),其他位则指示信号编号(异常返回),有一位指示是否产生了 core 文件等。终止状态可用 <sys/wait.h> 中的各个宏来查看,下表中 4 个互斥的宏可用来取得进程终止的原因。基于这 4 个宏中哪一个为真,就可选用其它宏来取得退出状态、信号编号等(很多平台都支持 WCOREDUMP 宏,但如果定义了 _POSIX_C_SOURCE 常量,有些平台就隐藏该定义)。

    下面这个程序就是利用这 4 个宏来打印进程终止状态的说明。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void pr_exit(int status){
	if(WIFEXITED(status))
		printf("normal terminaltion, 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){
		printf("1st fork error\n");
		exit(2);
	}else if(pid == 0)		// child
		exit(7);
	if(wait(&status) != pid){	// wait for child
		printf("1st wait error\n");
		exit(2);
	}
	pr_exit(status);		// and print its status

	if((pid=fork()) < 0){
		printf("2nd fork error\n");
		exit(2);
	}else if(pid == 0)
		abort();		// generates SIGABRT, signal number is 6
	if(wait(&status) != pid){
		printf("2nd wait error\n");
		exit(2);
	}
	pr_exit(status);

	if((pid=fork()) < 0){
		printf("3rd fork error\n");
		exit(2);
	}else if(pid == 0)
		status /= 0;		// generates SIGFPE, signal number is 8
	if(wait(&status) != pid){
		printf("3rd wait error\n");
		exit(2);
	}
	pr_exit(status);

	exit(0);
}

    运行结果如下。
$ ./exitStatusDemo.out 
normal terminaltion, exit status = 7
abnormal termination, signal number = 6(core file generated)
abnormal termination, signal number = 8(core file generated)
$ 

    如果一个进程有几个子进程,那么只要有一个子进程终止,wait 就返回。如果要等待一个指定的进程终止,waitpid 函数就派上用场了。对于 waitpid 函数中的 pid 参数的作用解释如下。
    * pid == -1:等待任一子进程,此时等效于 wait。
    * pid > 0:等待进程 ID 为 pid 的子进程。
    * pid == 0:等待组 ID 等于调用进程组 ID 的任一子进程。
    * pid < -1:等待组 ID 等于 pid 绝对值的任一子进程。
    参数 options 可以进一步控制 waitpid 的操作。此参数可以为 0 或者是下表中各常量按位或运算的结果(FreeBSD 8.0 和 Solaris 10 支持另一个非标准的可选常量 WNOWAIT,它使系统将终止状态已由 waitpid 返回的进程保持在等待状态,这样它可被再次等待)。

    如果一个进程 fork 了一个子进程,但不要它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的诀窍就是调用 fork 两次,正如下列这个程序所示。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void){
	pid_t		pid;

	if((pid=fork()) < 0){
		printf("1st fork error\n");
		exit(2);
	}else if(pid == 0){		// first child
		if((pid=fork()) < 0){
			printf("2nd fork error\n");
			exit(2);
		}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=%ld\n", (long)getppid());
		exit(0);
	}

	if(waitpid(pid, NULL, 0) != pid){	// wait for first child
		printf("waitpid error\n");
	}

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

    执行结果:
$ ./fork2timesDemo.out
$ second child, parent pid = 1

    注意,这里当原先的进程(即 exec 本程序的进程)终止时,shell 打印其提示符,因为这在第二个子进程打印其父进程 ID 之前发生。
    另外,Single UNIX Specification 包含了另一个取得进程终止状态的函数----waitid,此函数类似于 waitpid,但提供了更多的灵活性。
#include <sys/wait.h>
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
                                   /* 返回值:若成功,返回 0;否则,返回 -1 */

    waitid 也允许一个进程指定要等待的子进程,但它使用两个单独的参数表示要等待的进程所属的类型,而不是将此与进程 ID 或进程组 ID 组合成一个参数。id 参数的作用与 idtype 的值相关。该函数支持下表中的这几个 idtype 类型。

    options 参数是下表中各标志的按位或运算,这些标志指示调用者关注哪些状态变化。

    注意,WCONTINUED、WEXITED 和 WSTOPPED 这 3 个常量之一必须指定。
    infop 参数是指向 siginfo 结构的指针,该结构包含了造成子进程状态改变有关信号的详细信息。
    大多数 UNIX 系统实现还提供了 wait3 和 wait4 函数,它们提供的功能比上面几个 wait 函数提供的要多一个,这与附加参数有关,该参数允许内核返回由终止进程及其所有子进程使用的资源情况。资源统计信息(不同于资源限制)包括用户 CPU 时间总量、系统 CPU 时间总量、缺页次数、接收到信号的次数等,有关细节可查阅 getrusage(2) 手册页。
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>

pid_t wait3(int *statloc, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage);
                        /* 两个函数返回值:若成功,返回进程 ID;否则,返回 -1 */

文章评论

10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
总结2014中国互联网十大段子
总结2014中国互联网十大段子
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
程序员必看的十大电影
程序员必看的十大电影
编程语言是女人
编程语言是女人
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
鲜为人知的编程真相
鲜为人知的编程真相
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
为什么程序员都是夜猫子
为什么程序员都是夜猫子
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
那些争议最大的编程观点
那些争议最大的编程观点
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
我是如何打败拖延症的
我是如何打败拖延症的
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
如何成为一名黑客
如何成为一名黑客
 程序员的样子
程序员的样子
代码女神横空出世
代码女神横空出世
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
Java程序员必看电影
Java程序员必看电影
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
10个调试和排错的小建议
10个调试和排错的小建议
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
老程序员的下场
老程序员的下场
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
旅行,写作,编程
旅行,写作,编程
程序员和编码员之间的区别
程序员和编码员之间的区别
程序员应该关注的一些事儿
程序员应该关注的一些事儿
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
中美印日四国程序员比较
中美印日四国程序员比较
我的丈夫是个程序员
我的丈夫是个程序员
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有