多任务编程-fork()和waitpid()函数

一、fork() 函数

用于从一个已存在的进程中创建一个新进程,新进程称为子进程,原进程称为父进程。
头文件:
#include <sys/types.h>
#include <unistd.h>

pid_t child1,child2,father;
child1=fork();
函数格式pid_t fork(void); pid_t 为无符号整型
参数
返回值成功:子进程中返回0,父进程中返回子进程ID
失败:返回-1

失败有两个原因:
1、当前的进程数已经达到了系统规定的上限,这时 errno 的值被设置为 EAGAIN。

2、系统内存不足,这时 errno 的值被设置为 ENOMEM。

二、waitpid() 函数

当调用waitpid()函数时,当指定等待的子进程已经停止运行或结束了,则waitpid()会立即返回;但是如果子进程还没有停止运行或结束,则调用waitpid()函数的父进程则会被阻塞,暂停运行。
头文件:
#include <sys/types.h>
#include <sys/wait.h>

函数格式pid_t waitpid(pid_t pid,int *status,int options);

1、参数 pid_t pid,其含义为:等待的子进程识别码

参数说明
pid<-1等待进程组号为pid绝对值的任何子进程。
pid=-1等待任何子进程,此时的waitpid()函数就退化成了普通的wait()函数。
pid=0等待进程组号与目前进程相同的任何子进程,也就是说任何和调用waitpid()函数的进程在同一个进程组的进程。
pid>0等待进程号为pid的子进程。

2、int *status,其含义为:保存子进程的状态信息,如果不关心子进程状态则设为NULL。

说明
WIFEXITED(status)如果子进程正常结束,它就返回真;否则返回假。
WEXITSTATUS(status)如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的结束代码。
WIFSIGNALED(status)如果子进程因为一个未捕获的信号而终止,它就返回真;否则返回假。
WTERMSIG(status)如果WIFSIGNALED(status)为真,则可以用该宏获得导致子进程终止的信号代码。
WIFSTOPPED(status)如果当前子进程被暂停了,则返回真;否则返回假。
WSTOPSIG(status)如果WIFSTOPPED(status)为真,则可以使用该宏获得导致子进程暂停的信号代码。

**3、**int options,其含义为:也可以控制waitpid()函数的行为,如果不需要可以设为0。

参数说明
WNOHANG如果pid指定的子进程没有结束,则waitpid()函数立即返回0,而不是阻塞在这个函数上等待;如果结束了,则返回该子进程的进程号。
WUNTRACED如果子进程进入暂停状态,则马上返回。

附上代码段:

/***fork()&waitpid()***/
/*父进程、子进程之间的关系*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
	pid_t child1,child2,father;	
	child1=fork();				//创建子进程child1
	if(child1 == (-1))			//child1创建失败处理
	{
		printf("child1 fork error\n");
		exit(1);			//异常退出
	}
	else if(child1 == 0)
	{
		printf("I am child1 program! and I execute 'ls -l'\n");
	
		/*
		 * execlp 从PATH环境变量中查找相应的命令
		 * 成功不会返回,失败返回-1
		 */
	
		if(execlp("ls","ls","-l",NULL) == -1)
		{
		printf("execlp error\n");
		}
	}

	/*在父进程中再创建进程child2,然后等待两个子进程的结束*/
	
	else
	{
		child2=fork();			//创建child2进程
		if(child2 == -1)		//child2进程创建失败处理
		{
		printf("child2 fork error\n");
		exit(1);
		}
		else if(child2 == 0)
		{
			printf("I am child2! and will sleep for 5s!\n");
			sleep(5);		//睡眠5s
			printf("I am child2! and will exit!\n");
			exit(0);
		}
		printf("I am father progress\n");
		father=waitpid(child1,NULL,0);

		/*阻塞式等待
		 *waitpid()函数 
		* 成功,则返回子进程的进程号;如果有错误发生,则返回-1
		*/

		if(father == child1)
		{
			printf("I am father progress.\n");
			printf("I get child1 exit code:%d\n",child1);
		}
		else
		{
			printf("Father error!\n");
		}

		do
		{
			father=waitpid(child2,NULL,WNOHANG);//非阻塞式等待
			if(father == 0)
			{
				printf("I am father progress.child2 has not exited!\n");
				sleep(1);
			}
		}while(father == 0);

		if(father==child2)
		{
			printf("I am father progress.\n");
			printf("I get child2 exit code:%d\n",child2);
		}
		else
		{
			printf("Father error\n");
		}
	}
	exit(0);
}

感谢。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值