进程控制(二):进程等待

文章目录


进程控制(二)

延续对于上文进程结束,我们继续对于进程控制进行学习,本文我们主要是对于进程等待进行学习,进程等待,我们在前文初步接触进程的时候,我们知道,进程等待是指我们在运行该进程的时候,在等待资源,当有了资源分配后,便可以运行该进程,在本文中,我们认识的进程等待是指,子进程退出时,先进入僵尸状态,然后父进程进行等待(wait/waitpid)来获取子进程退出信息,这个过程叫做进程等待。

进程等待

进程等待,是子进程退出信息被父进程接收时,父进程处于等待状态的一种描述。

进程等待是指通过系统调用wait/waitpid,来进行对子进程进行状态检测与回收的功能。

  • 子进程退出时,如果父进程没有接收信息,那么会导致僵尸进程的问题,造成内存泄漏,所以父进程必须通过进程等待来回收子进程退出信息。(必要
  • 通过回收子进程的退出信息,也可以知道子进程退出码,以及是否出现异常,status。(可选

所以,我们必须要实现进程等待,防止内存泄漏,对于得到的子进程退出信息,我们可以选择性的利用,可有可无,看自己需求。

wait函数

wait函数,可以实现进程等待,只有一个参数,status,输出型参数,可以获得子进程退出信息

wait函数在2号手册上,头文件也可以表明,wait函数以及waitpid函数是系统调用接口,通过该函数来访问操作系统,使得操作系统对于子进程进行回收处理。

core dump,以后会用到,现在不需要掌握,只需要知道,这是用来进行调试的。

c 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>

#define N 10

void RunChild()
{
   int cnt=5;
   while(cnt)
   {
      printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppid
      sleep(1);
      cnt--;
   }
   //printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppid
   //sleep(15);
}

int main()
{
    //实现创建子进程,并对于子进程进行等待
    for(int i=0;i<N;i++)
    {
      pid_t id=fork();//创建子进程
      if(id==0)
      {
        RunChild();
        exit(i);//退出码
      }
      //父进程执行下面信息
      printf("create Child proc : %d success\n",id);
    }
    sleep(10);
    return 0;
}

上述代码,我们并没有是wait,会造成内存泄漏,下面我们来通过父进程来接收子进程的退出信息。

c 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>

#define N 10

void RunChild()
{
   int cnt=5;
   while(cnt)
   {
      printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppid
      sleep(1);
      cnt--;
   }
   //printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppid
   //sleep(15);
}

int main()
{
    //实现创建子进程,并对于子进程进行等待
    for(int i=0;i<N;i++)
    {
      pid_t id=fork();//创建子进程
      if(id==0)
      {
        RunChild();
        exit(i);//退出码
      }
      //父进程执行下面信息
      //wait;进程等待
      
      printf("create Child proc : %d success\n",id);
   }
    //进程等待
    for(int i=0;i<N;i++)
    {
        //会实现进程的等待
        pid_t id=wait(NULL);//wait等待是随机的,等待还没有被接收信息的子进程,有几个子进程就需要等几次。
        //int status=0;
        //pid_t id=wait(&status);//传地址,操作系统来进行存储子进程退出信息
        if(id>0)
        {
          //printf("wait %d success\n ; exit sig: %d\n",id,WEXITSTATUS(status));
          printf("wait %d success\n",id);
        }
    }
    return 0;
}

waitpid函数

waitpid函数,其拥有三个参数,功能相较于wait更多,可以认为waitpid可以包含wait的功能,wait的功能比较单一,智能获取状态码status,而且是随机等待子进程。

c 复制代码
#include <sys/types.h>
#include <sys/wait.h>
 
pid_t waitpid(pid_t pid, int* status, int options);

参数介绍

返回值pid_t:

  • 大于0,表示等待子进程成功,返回值是子进程的pid
  • 小于0,表示等待子进程失败
  • 等于0,表示等待条件还没有就绪,此时父进程可以做自己的事情

pid参数:

  • 大于0,表示等待指定的子进程
  • pid = -1 ,表示等待随机子进程

status参数:

  • NULL,表示不需要子进程的状态码
  • 反之,作为输出型参数,操作系统将子进程退出信息写入status中

options参数:

  • 0,表示阻塞等待
  • WNOHONG,表示非阻塞等待

wait/waitpid获取子进程状态码的过程

wait和waitpid都是系统调用,为什么要通过系统调用函数,而不是库函数来实现该功能,这是因为,由于进程具有独立性,相互不影响,所以一般的函数无法访问到另一进程的内容,而系统调用,可以在全局上(操作系统的角度)来找到子进程PCB,得到状态码

等待流程

  1. 子进程运行完毕后,进入僵尸状态(Z),将退出码信息存储到子进程PCB中(exit_code,exit_signal),释放代码,以及数据,保留task_struct结构体信息。
  2. 父进程通过wait/waitpid,通过系统调用,得到子进程PCB中的退出信息,将推出信息,以位图的方式,写入到int类型的status参数,从而父进程得到子进程的推出信息。

exit_code:表示退出码

exit_signal:表示结束信号,也就是判断是否异常,如果为0,表示正常,如果非零,那就是接收了终止信号 kill -num,其中num==exit_signal

实现方式:

exit_signal == status&0x7F == WIFEXITED(status)

exit_code == status>>8&0xFF == WEXITSTATUS(status)

进程等待相关的宏

WEXITSTATUS(status):表示输出退出码(exit_code)

WNOHONG:表示非阻塞等待,用于waitpid的option参数。

WIFEXITED(status):通过状态码,表示子进程是否正常结束(是否异常),如果正常,返回ture

总结

进程等待,是父进程必须要完成的事情,是为了防止内存泄漏,也是为了知道子进程完成任务情况(由状态码得出结论),主要是了解wait/waitpid函数,以及status参数的构成,为什么能表示进程的三种退出情况,以及waitpid函数的非阻塞等待宏WNOHONG,还有退出码WEXITSTATUS,还有判断子进程是否正常退出的宏命令WIFEXITED。

相关推荐
ac.char2 分钟前
在 Ubuntu 下使用 Tauri 打包 EXE 应用
linux·运维·ubuntu
Cachel wood21 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Youkiup29 分钟前
【linux 常用命令】
linux·运维·服务器
qq_2975046133 分钟前
【解决】Linux更新系统内核后Nvidia-smi has failed...
linux·运维·服务器
weixin_437398211 小时前
Linux扩展——shell编程
linux·运维·服务器·bash
小燚~1 小时前
ubuntu开机进入initramfs状态
linux·运维·ubuntu
小林熬夜学编程1 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
炫彩@之星1 小时前
Windows和Linux安全配置和加固
linux·windows·安全·系统安全配置和加固
hhhhhhh_hhhhhh_1 小时前
ubuntu18.04连接不上网络问题
linux·运维·ubuntu
冷心笑看丽美人1 小时前
探秘 DNS 服务器:揭开域名解析的神秘面纱
linux·运维·服务器·dns