Linux详解:进程等待

发布于:2024-04-30 ⋅ 阅读:(22) ⋅ 点赞:(0)

进程等待

等待的必要性

  • 子进程退出,父进程不进行回收的话,就可能造成僵尸进程,进而造成内存泄露

  • 如果进程进入了僵尸状态,kill也杀不掉这个进程。因为谁也杀不死一个已经死去的进程

  • 父进程派给子进程的任务完成的如何,使用者应该直到结果。子进程的任务是完成了还是未完成。

  • 父进程通过进程等待(wait)的方式,回收子进程的资源,获取子进程的退出信息

  • 父进程通过wait的方式,回收子进程的资源

    子进程的退出信息,保存在子进程的pcb中。

进程等待的方法

#include<sys/types.h>
#incldue<sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

wait

pid_t wait(int *status);
  • 默认进行阻塞等待,子进程没有退出,父进程就一直等待。
  • 等待父进程的任意一个子进程退出。
  • 返回值:
    • >0:等待成功,返回值是等待子进程的pid
    • <0:等待失败
  • 参数:输出型参数,获取子进程的退出状态,如果不关心则可以设置为NULL

frok之后,父子进程谁先运行,不确定,是由操作系统的调度器运行。但是谁最后退出是确定的,父进程一定要最后退出,因为要等待子进程运行结束之后回收子进程。

waitpid

pid_t waitpid(pid_t pid, int *status, int options);
  • 返回值:
    • >0:等待成功,返回值是等待子进程的pid
    • <0:等待失败
  • 参数
    • pid
      • pid=-1,等待人一个子进程,与wait等效
      • pid>0,等待其进程id与pid值相等的子进程
    • status:输出型参数,获取子进程的退出状态,如果不关心则可以设置为NULL
    • options:0、非阻塞

获取子进程status

  • wait和waitpid,都有一个status参数,这个参数是一个输出型参数,由操作系统进行填充
  • 如果传递NULL,表示不关心子进程的退出状态信息
  • 如果不是NULL,则操作系统会根据该参数,将子进程的退出信息反馈给父进程
  • status不能简单的当作整形来看待,应该当成位图来看,只考虑status的低16位。
status:0000 0000 0000 0000 0000 0000 0000 0000

信号编号 进程退出码 表示状态
0 0 没有异常,结果正确
!0 0 出现异常,退出码无意义
0 !0 没有异常,结果错误
!0 !0 出现异常,退出码无意义
0~7,进程出现异常,收到的信号编号
9~15,进程正常结束的退出码

信号编号:status&0x7F
退出码:(status >> 8)& 0xFF

status:

  • WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否正常退出)。判定当前进程的退出信号是否为0,为0就为真,不为0就是假。
  • WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)。

因为进程具有独立性,所以父子无法直接互相修改对方的数据之后,让对方看到。

因为读取子进程退出信息,本质上是读取内核数据,所以需要调用系统接口。

#include<sys/types.h>
#incldue<unistd.h>
#include<sys/wait.h>
int main()
{
	pid_t id = fork();
	if(id == 0)
	{
		int cnt = 5;
		while(cnt)
		{
			printf("child is running, pid:%d, ppid:%d",getpid(),getppid());
			sleep(1);
			cnt--;
		}
		exit(0);
	}
	int status = 0;
	pid_t rid = waitpid(id,&status,0);
	if(id>0)
	{
		printf("wait success,rid:%d , status:%d, exitsigno:%d, exitcode    :%d\n",rid,status,(status&0x7F),((status>>8)&0xFF));
	}
}

阻塞等待 与 非阻塞等待

父进程阻塞等待,当子进程还在执行时,没有返回,父进程会将自己设置为阻塞状态,一直等待着子进程结束回收。

非阻塞等待,父进程检查子进程是否返回,如果子进程没有返回,不进行等待,父进程立刻返回,返回值为0。如果子进程已经返回,则返回子进程的id。

WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予等待,若正常结束,则返回该子进程的id。

单次调用:非阻塞

基于非阻塞的轮询访问

机器宕机了,操作系统没有反应 – hang住了