Linux--进程--进程-父进程退出

1.进程退出函数

进程退出分为正常退出&异常退出

正常退出:

        1、main函数调用return

        2、进程调用exit(),标准c库

        3、进程调用_exit()或者_Exit(),属于系统调用

        补充

        1、进程最后一个线程返回

        2、最后一个线程调用pthread_exit

异常退出:

        1、调用abort,等于放弃当前进程

        2、当进程收到某些信号时,如ctrl+c

        3、最后一个线程对取消(cancellatio)请求做出响应
exit函数:

#include 


void exit(int status);
void _Exit(int status);

#include 


void _exit(int status);
 

代码:

#include 
#include 
#include 
#include 
 
int main()
{
	pid_t pid;
	int cnt=0;	
	pid=vfork();
	
 
	if(pid>0){
		while(1){
			printf("cnt=%d\n",cnt);
			printf("this is father print%d\n",getpid());
			sleep(1);
		}
	}
	if(pid==0){
		while(1){
			printf("this is child print,pid=%d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt==3){
				//break;
				//exit(0);
				//_exit(0);
				_Exit(0);
			}
		}	
	}
 
	return 0;
}

进程退出调用(exit\_exit\_Exit)函数,尽量调用exit函数,调用后会对子进程调用的数据进行一下冲刷处理再退出,_exit\_Exit是直接退出。

结果:

2.父子进程退出

僵尸进程:子进程退出状态不被收集,变成僵尸进程(僵死进程)Z+状态

孤儿进程:父进程退出,子进程还在运行;此时父进程会被init进程吸收,其pid=1;Linux系统作用

调用wait()阻塞函数:

#include 
#include 
pid_t wait(int *status);

作用:等待子进程完成或者退出,之后通常运行父进程

 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

参数:

参数status(注意此为指针)用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像这样:pid = wait(NULL);
返回值:

如果成功,wait会返回被收集的子进程的进程ID;
如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。
多数使用wait函数
 

2.waitpid函数:  wait使调用者阻塞,waitpid有一个选项,可以使调用者不阻塞。

#include 
#include 
pid_t waitpid(pid_t pid, int *status, int options)

参数

status:与wait的一样用法。


pid:从参数的名字pid和类型pid_t中就可以看出,这里需要的是一个进程ID。但当pid取不同的值时,在这里有不同的意义。

对于waitpid函数中pid参数作用解释如下:

        pid=-1        等待任一子进程,&wait等效

        pid>0        等待其进程ID与pid相等的子进程

        pid==0        等待其组ID等于调用进程组ID的任一子进程

        pid<-1        等待其组ID等于pid绝对值的任一子进程
 


options:提供了一些额外的选项来控制waitpid,目前在Linux中只支持:WNOHANG和WUNTRACED两个选项,这是两个常数,可以用"|"运算符把它们连接起来使用;比如ret=waitpid(-1,NULL,WNOHANG | WUNTRACED); 如果我们不想使用它们,也可以把options设为0,如ret=waitpid(-1,NULL,0); 如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。而WUNTRACED参数,由于涉及到一些跟踪调试方面的知识,加之极少用到,可以自行查阅相关材料。

返回值:waitpid的返回值比wait稍微复杂一些,一共有三种情况:
① 当正常返回的时候,waitpid返回收集到的子进程的进程ID;
② 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;  一般options写WNOHANG    
③ 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD;

waitpid提供了wait函数不能实现的3个功能:

① waitpid等待特定的子进程, 而wait则返回任一终止状态的子进程;
② waitpid提供了一个wait的非阻塞版本;
③ waitpid支持作业控制。用于检查 wait() 和 waitpid() 两个函数返回终止状态的宏: 这两个函数返回的子进程状态都保存在status指针中,用以下3个宏可以检查该状态:
WIFEXITED(status): 若为正常终止, 则为真。此时可执行 WEXITSTATUS(status): 取子进程传送给exit或_exit参数的低8位.
WIFSIGNALED(status): 若为异常终止, 则为真。此时可执行 WTERMSIG(status): 取使子进程终止的信号编号.
WIFSTOPPED(status): 若为当前暂停子进程, 则为真。此时可执行 WSTOPSIG(status): 取使子进程暂停的信号编号


代码:

#include 
#include 
#include 
#include 
 
int main()
{
	pid_t pid;
	int cnt=0;
	int status=10;
	
	pid=fork();
	
 
	if(pid>0){
//		wait(&status);
		waitpid(pid,&status,WNOHANG);
		printf("child quit,child status=%d\n",WEXITSTATUS(status));
		
		while(1){
			printf("cnt=%d\n",cnt);
			printf("this is father print%d\n",getpid());
			sleep(1);
		}
	}
	if(pid==0){
		while(1){
			printf("this is child print,pid=%d\n",getpid());
			sleep(1);
			cnt++;
			if(cnt==3){
				//break;
				//exit(0);
				//_exit(0);
				exit(3);
			}
		}	
	}
 
	return 0;
}

运行:

Linux--进程--进程-父进程退出_第1张图片子进程、父进程同时运行3次,子进程退出,父进程运行;非阻塞下,子进程变成僵尸进程

你可能感兴趣的:(嵌入式Linux学习,linux)