Linux系统编程 Part2 子进程的创建与控制

exec函数族
man exec ~~~
int execl(const char*path,const char arg,…)
int execlp(const char
file,const char * arg,…)
后缀中
v 命令行参数中的argv
e environment,需要添加环境变量表
l list

//execlp 实现ls -al
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(){
	pid_t pid;

	pid=fork();

	if(pid<0){
		perror("fork err!");
		exit(1);
	}else if(pid==0){
	//	printf("son process");
		execlp("ls","ls","-al",NULL);
	}else {
		wait(NULL);
		printf("This is father process\n");
	}

	return 0;
}

重定向输出函数 dup2(3,1) 将STD_OUT输出重定向到3的文件中。

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

int main(){
	pid_t pid;
	pid=fork();
	//打开ps.out文件 
	int fd=open("ps.out",O_WRONLY|O_CREAT|O_TRUNC,0644);
	if(pid<0){
		perror("fork err\n");
		exit(1);
	}else if (pid >0){
		wait(NULL);
		printf("Father process! !!!!!!!\n");
		
	}else{
		dup2(fd,STDOUT_FILENO); //== dup2(fd,1);
		execlp("ps","ps","-aux",NULL);
		printf("Son process ends!!!!!!!!!\n");
	}
	return 0;
}






孤儿进程

//父进程终止后,子进程的父进程变成pid=1的进程

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

int main(){

	pid_t pid;
	pid=fork();
	if(pid==-1){
		perror("fork error!\n");
	}else  if (pid==0){

		printf("child=%d  parentid=%d\n",getpid(),getppid());
		sleep(3);
		printf("child=%d  parentid=%d\n",getpid(),getppid());
	}else {
		printf("father id=%d",getpid());
	
	}

	
	return 0;

}

僵尸进程
进程终止,父进程尚未回收,子进程残留资源存放于内核中,变成僵尸进程。注:僵尸进程已经终止,无法用kill清除!。

wait函数三个作用:阻塞等待子进程退出;回收子进程残留资源;获取子进程结束状态。

//子进程未得到处理 结束后成为僵尸进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>


int main(){

	pid_t pid;
	pid=fork();
	if(pid<0){
		perror("fork error!\n");
		exit(1);
	}else  if (pid==0){
		
		printf("child=%d  parentid=%d\n",getpid(),getppid());
		sleep(3);
		printf("----------son process died--------------\n");
	}else {
		while(1){
			printf("father id=%d son proce%d\n",getpid(),pid);
			sleep(1);	
		}
	}

	return 0;

}


进程退出的宏:
WIFEXITED(status) 非0 则进程正常结束
WEXITSTATUS(status) 若上述宏非0 则获取进程退出状态(exit 参数)。

WIFSIGNALED(status) 非0 则进程异常终止
WTERMSIG(status) 若上述宏非0 则使用该宏获取进程终止进程的信号。

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

int main(){

	pid_t pid;
	int status;
	pid=fork();
	if(pid<0){
		perror("fork error!\n");
		exit(1);
	}else  if (pid==0){
		
		printf("child=%d  parentid=%d\n",getpid(),getppid());
		sleep(3);
		printf("----------son process died--------------\n");
		exit(22);
	}else {

		pid_t wpid=wait(&status);  
		if(wpid==-1){
			perror("wait error!\n");
			exit(1);
		}
	
		//使用宏
		if(WIFEXITED(status)){
			printf("child exit with %d\n",WEXITSTATUS(status));
		}

		while(1){
			printf("father id=%d son proce%d\n",getpid(),pid);
			sleep(1);	
		}
	
	return 0;

	}
}

//执行该程序时,根据输出的子进程pid,向其发送kill信号 退出值15

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

int main(){

	pid_t pid;
	int status;
	pid=fork();
	if(pid<0){
		perror("fork error!\n");
		exit(1);
	}else  if (pid==0){
		
		printf("child=%d  parentid=%d\n",getpid(),getppid());
		sleep(13);
		printf("----------son process died--------------\n");
		exit(22);
	}else {

		pid_t wpid=wait(&status);  
		if(wpid==-1){
			perror("wait error!\n");
			exit(1);
		}
	
		//使用宏
		if(WIFEXITED(status))
			printf("child exit with %d\n",WEXITSTATUS(status));
		
		if(WIFSIGNALED(status))
			printf("child unormally eixted with signal%d\n",WTERMSIG(status));
		
		while(1){
			printf("father id=%d son proce%d\n",getpid(),pid);
			sleep(1);	
		}
	return 0;

	}
}

wait函数只能回收最先结束的子进程,要想回收多个子进程,可用waitpid函数指定回收。
pid_t waitpid(pid_t pid,int *status,int options); 指定第三个参数可以不阻塞。
pid参数:

  • 0 回收指定pid的子进程

  • -1 回收任意子进程 相当于wait
  • 0回收和当前调用wiatpid一个组的所有子进程 通常情况下,父子进程同组,使用等于-1
  • <-1 回收指定进程组内的任意子进程
    参数3若为WNOHANG,非阻塞
//下图所示,pid为7367的子进程被回收,其他子进程处于未处理状态。


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

int main(int argc,char *argv[]){
	int n=5,i;
	pid_t p1,p2;
	
	if(argc==2)
		n=atoi(argv[1]);

	for(i=0;i<n;i++){
		p1=fork();
		if(p1==0)
			break; //若是子进程则结束循环 i永远为0
		else if(i==3)//单独回收第三个子进程的情况。先保存pid
			p2=p1;
	}

	if(n==i){
		sleep(n);
		printf("This is parent,pid=%d\n",getpid());
		waitpid(p2,NULL,0);
		while(1);
		
	}else{
		printf("This is child ,pid=%d and parentpid=%d\n",getpid(),getppid());
			
	}

在这里插入图片描述

//waitpid 持续等待所有子进程结束。 
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc,char *argv[]){

	int n=5,i;
	pid_t p1,p2;
	pid_t wpid;

	if(argc==2)
		n=atoi(argv[1]);

	for(i=0;i<n;i++){
		p1=fork();
		if(p1==0)
			break; //若是子进程则结束循环 i永远为0
		else if(i==3)//单独回收第三个子进程的情况。先保存pid
			p2=p1;
	}


	if(n==i){
		sleep(n);
		printf("This is parent,pid=%d\n",getpid());
		do{
			//若wpid为0 则子进程仍在执行。 -1表示尽可能的回收
			wpid=waitpid(-1,NULL,WNOHANG);
			if(wpid>0) n--;   //每结束一个子进程 n--

		}while(n!=0); //n=0 所有子进程结束。

	//	while(1);
		
	}else{
	
		printf("This is child ,pid=%d and parentpid=%d\n",getpid(),getppid());
		
	
	}


	//return 0;

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值