3.4.8.waitpid(等待指定子进程的pid)介绍

3.4.8.waitpid介绍
3.4.8.1、waitpid和wait差别

相同点 是功能, 不同点是 使用 方法
(1)基本功能一样,都是用来回收子进程
(2)waitpid可以回收指定 PID 的子进程
(3)waitpid可以阻塞式或非阻塞式两种工作模式

3.4.8.2、waitpid原型介绍
(1)参数
(2)返回值


3.4.8.3、代码实例
(1)使用waitpid实现wait的效果
ret = waitpid(-1, &status, 0);      -1表示不等待某个特定PID的子进程而是回收任意一个子进程,0表示用默认的方式(阻塞式)来进行等待,返回值ret是本次回收的子进程的PID
(2)ret = waitpid(pid, &status, 0);        等待回收PID为pid的这个子进程,如果当前进程并没有一个ID号为pid的子进程,则返回值为-1;如果成功回收了pid这个子进程则返回值为回收的进程的PID
(3)ret = waitpid(pid, &status, WNOHANG);这种表示父进程要非阻塞式的回收子进程。此时如果父进程执行waitpid时子进程已经先结束等待回收则waitpid直接回收成功,返回值是回收的子进程的PID;如果父进程waitpid时子进程尚未结束则父进程立刻返回(非阻塞),但是返回值为0(表示回收不成功)。

 代码:

ret = waitpid(-1,&status,0); /* waitpid ,-1表示不管是那个子进程都回收 ,0 表示 阻塞式 */

只是 更改了 这一句,其他的 和 wait 都一样,效果也一样

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t p1 = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	p1 = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == p1)
	{
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		return  99;
	}	
	else if (p1 > 0)
	{
		/* 这里一定是 父进程 */
		ret = waitpid(-1,&status,0); /* waitpid ,-1表示不管是那个子进程都回收 ,0 表示 阻塞式 */
		printf("子进程已经被回收,子进程pid = %d \n", ret);
		printf("子进程是否正常退出:%d \n", WIFEXITED(status));  /* WIFEXITED  判断是否正常退出 */
		printf("子进程是否 非正常退出:%d \n", WIFSIGNALED(status));  /* WIFSIGNALED 判断是否 非正常退出 */
		printf("子进程正常终止情况下的  进程返回值:%d \n", WEXITSTATUS(status));  /* WEXITSTATUS 正常终止情况下的  进程返回值 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

运行结果:

 实例 2 , waitpid  用指定 pid 回收 子进程

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t p1 = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	p1 = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == p1)
	{
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		return  99;
	}	
	else if (p1 > 0)
	{
		printf(" 父进程中打印 子进程id = %d \n ",p1);                   /* 这里一定是 父进程 */
		/* 这里一定是 父进程 */
		ret = waitpid(p1,&status,0); /* waitpid ,-1表示不管是那个子进程都回收 ,0 表示 阻塞式 */
		printf("子进程已经被回收,子进程pid = %d \n", ret);
		printf("子进程是否正常退出:%d \n", WIFEXITED(status));  /* WIFEXITED  判断是否正常退出 */
		printf("子进程是否 非正常退出:%d \n", WIFSIGNALED(status));  /* WIFSIGNALED 判断是否 非正常退出 */
		printf("子进程正常终止情况下的  进程返回值:%d \n", WEXITSTATUS(status));  /* WEXITSTATUS 正常终止情况下的  进程返回值 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

运行结果:

 实例 3 ,如果传一个 错误的 pid  , waitpid会返回 什么呢?????

传一个 错误的 pid  : p1+6

ret = waitpid(p1+6,&status,0); /* waitpid ,-1表示不管是那个子进程都回收 ,0 表示 阻塞式 */

运行结果:

实例 4  waitpid   非阻塞式 回收 WNOHANG 

ret = waitpid(p1,&status,WNOHANG);  /* waitpid ,-1表示不管是那个子进程都回收 ,WNOHANG  表示 非阻塞式 */

代码:

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t p1 = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	p1 = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == p1)
	{
		/* 这里一定是 子进程 , 为了 保证 父进程 先执行 waitpid 非阻塞式 回收 ,子进程sleep , 先让父进程执行 */
		sleep(1);
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		return  99;
	}	
	else if (p1 > 0)
	{
		printf(" 父进程中打印 子进程id = %d \n ",p1);                   /* 这里一定是 父进程 */
		/* 这里一定是 父进程 */
		ret = waitpid(p1,&status,WNOHANG);  /* waitpid ,-1表示不管是那个子进程都回收 ,WNOHANG  表示 非阻塞式 */
		printf("子进程已经被回收,子进程pid = %d \n", ret);
		printf("子进程是否正常退出:%d \n", WIFEXITED(status));  /* WIFEXITED  判断是否正常退出 */
		printf("子进程是否 非正常退出:%d \n", WIFSIGNALED(status));  /* WIFSIGNALED 判断是否 非正常退出 */
		printf("子进程正常终止情况下的  进程返回值:%d \n", WEXITSTATUS(status));  /* WEXITSTATUS 正常终止情况下的  进程返回值 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

运行结果:

 

 实例 4  waitpid   非阻塞式 回收 WNOHANG 

把 sleep 加入到 父进程 ,让子进程先结束,子进程进入僵尸进程后 ,父进程 去回收

代码:

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


int main(void)
{
    /* 接收 fork 的返回值 */
    pid_t p1 = -1;
    /* 接收 wait waitpid 的返回值 */
    pid_t ret = -1;
    /*  wait waitpid 传参,进程状态信息 */
    int status = -1;
    
    
    p1 = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
    
    if(0 == p1)
    {
        /* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
        printf("子进程 child pid = %d \n", getpid()); 
        return  99;
    }    
    else if (p1 > 0)
    {
         /*  父进程 加入 sleep */
        sleep(1);
        printf(" 父进程中打印 子进程id = %d \n ",p1);                   /* 这里一定是 父进程 */
        /* 这里一定是 父进程 */
        ret = waitpid(p1,&status,WNOHANG);  /* waitpid ,-1表示不管是那个子进程都回收 ,WNOHANG  表示 非阻塞式 */
        printf("子进程已经被回收,子进程pid = %d \n", ret);
        printf("子进程是否正常退出:%d \n", WIFEXITED(status));  /* WIFEXITED  判断是否正常退出 */
        printf("子进程是否 非正常退出:%d \n", WIFSIGNALED(status));  /* WIFSIGNALED 判断是否 非正常退出 */
        printf("子进程正常终止情况下的  进程返回值:%d \n", WEXITSTATUS(status));  /* WEXITSTATUS 正常终止情况下的  进程返回值 */
    }
    else
    {
        /* 这里一定是 fork出错了  */
        perror("fork");
        return -1;
    }
    

    
    
    return 0;
}
运行结果:

 

3.4.8.4、竟态初步引入
(1)竟态全称是:竞争状态,多进程环境下,多个进程同时抢占系统资源(内存、CPU、文件IO)

进程1 读1.txt, 进程2 也同时读1.txt


(2)竞争状态对OS来说是很危险的,此时OS如果没处理好就会造成结果不确定。

  如果 没有 sleep 我们就不确定 到底是 父进程先 结束,还是 子进程先结束!!!


(3)写程序当然不希望程序运行的结果不确定,所以我们写程序时要尽量消灭竞争状态。操作系统给我们提供了一系列的消灭竟态的机制我们需要做的是在合适的地方使用合适的方法来消灭竟态。
 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大漠飞鹰6666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值