Linux_进程控制(二)

wait和waitpid

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int * status);
//成功返回被等待进程pid,失败返回-1
//参数获取子进程退出状态,不关心可设为NULL
pid_t waitpid(pid_t pid, int *status, int options);
/*
**正常返回收集到的子进程id
**若设置了WNOHANG选项,调用中发现没有已退出的子进程可收集,返回0
**出错返回-1
**pid:"=-1",等待任一个子进程,与wait等效;">0"等待id为pid的子进程
**status:"WIFEXITED(status)",查看进程是否正常退出;"WEXITSTATUS(status)",查看进程退出码
**options:"WNOHANG",若指定子进程未结束,返回0,否则返回子进程id
*/

1、获取子进程status

  • wait和waitpid都有status参数,是一个输出型参数
  • 传值NULL表示不关心子进程退出状态信息
  • 操作系统会根据该参数将子进程退出信息反馈给父进程

研究status低16比特位:

  • 正常终止:8位退出状态 + 8位零
  • 被信号所杀:8位未用 + core dump标志 + 终止信号
#include<sys/wait.h>
#include<unistd.h>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

int main()
{
	pid_t pid = fork();
	if(pid == -1)
	{
		perror("error");
		exit(1);
	}
	if(pid == 0)
	{
		sleep(20);
		exit(8);
	}
	else
	{
		int status;
		int ret = wait(&status);
		if(ret > 0 && (status & 0x7F) == 0)
		{
			//正常退出
			cout<<"child exit code:"<<((status>>8) & (0xFF))<<endl;
		}
		else if(ret > 0)
		{
			//异常退出
			cout<<"sig code:"<<((status) & (0x7F))<<endl;
		}
	}
	return 0;
}

在这里插入图片描述在这里插入图片描述
第一次运行什么都不做,程序正常退出,返回退出状态码;
第二次运行时,打开另一个终端,找到子进程id,kill掉,程序异常退出,返回终止信号码;

进程的阻塞等待方式

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

using namespace std;

int main()
{
	pid_t pid = fork();
	if(pid == -1)
	{
		perror("error");
		exit(1);
	}
	if(pid == 0)
	{
		cout<<"child pid:"<<getpid()<<endl;
		sleep(5);
		exit(257);
	}
	else
	{
		int status = 0;
		pid_t ret = waitpid(-1, &status, 0);
		if(WIFEXITED(status) && (ret == pid))
		{
			cout<<"child exit code:"<<WEXITSTATUS(status)<<endl;
		}
		else
		{
			cout<<"failed"<<endl;
			exit(1);
		}
	}
	return 0;
}

在这里插入图片描述
2、进程程序替换

替换原理

  • 用fork创建子进程后执行的是和父进程相同的程序,有可能执行不同的代码分支
  • 子进程往往要调用一种exec函数以执行另一个程序
  • 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行
  • 调用exec并不创建新进程,所以调用exec前后该进程的id并未改变

替换函数
在这里插入图片描述
只有execve是真正的系统调用,上面几个最终调用execve
在这里插入图片描述
函数解释

  • 调用成功则加载新程序开始执行,不再返回
  • 调用出错返回-1

命名解释

  • l(list):参数采用列表
  • v(vector):参数采用数组
  • p(path):自动搜索环境变量PATH
  • e(env):自己维护环境变量

举例

#include<unistd.h>

int main()
{
	char *const argv[] = {"ps", "-ef", NULL};
	char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
	execl("/bin/ps", "ps", "-ef", NULL);
	execlp("ps", "ps", "-ef", NULL);
	execle("ps", "ps", "-ef", NULL, envp);
	execv("/bin/ps", argv);
	execvp("ps", argv);
	execve("/bin/ps", argv, envp);
	return 0;
}

调用exec执行ls -l指令

#include<unistd.h>

int main()
{
	char *const argv[] = {"ls","-l",NULL};
	char *const envp[] = {"PATH=/bin:/usr/bin","TERM=console",NULL};
	execve("/bin/ls",argv,envp);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值