Linux操作系统下fork、wait函数的运用和子进程的完全释放

一、fork函数

1.函数原型:pid_t fork (void);

头文件:#include <sys/types.h>    #include <unistd.h>

参数 :void

返回值:pid_t类型

函数描述:man 2 fork可以看到man手册对fork的主要描述

DESCRIPTION

       fork()  creates  a new process by duplicating the calling process.  The
       new process is referred to as the child process.  The  calling  process
       is referred to as the parent process.

      The child process and the parent process run in separate memory spaces.

RETURN VALUE
       On success, the PID of the child process is returned in the parent, and
       0  is returned in the child.  On failure, -1 is returned in the parent,
       no child process is created, and errno is set appropriately.

使用fork函数会在当前进程下创建一个新的进程,新进程是当前进程的子进程,当前进程是新进程的父进程,并且它两的内容基本是相同的,但是也有一些不同。如果子进程创建成功fork函数返回子进程的PID,失败返回-1。

2.为什么它两的内容基本是相同的,但是也有一些不同?

进程的运行操作系统必然要给该进程运行分配必须要的内存空间

子进程将用户空间是完全复制过去的包括(代码段、.bss、.data、常量区,堆区、栈区),当复制内核空间时,内核空间有一个task_struct结构体有一些不会复制过去

task_struct结构体是存储当前进程信息的结构体包括PID、PPID、UID、EUID、进程块本身、当前目录、当前终端信息、线程基本信息、可以访问的内存地址空间等等。子进程的内存由操作系统分配的所有他们的PID,PPID必然是不同的。注意:操作系统分配的虚拟内存,不是实际的物理内存。

僵尸进程:僵尸进程是由于子进程提前结束,父进程还在运行,但是父进程没有关心子进程的结束状态,当子进程运行结束时,系统会回收子进程的分配空间,但是子进程的内核空间中的task_struct结构体不会释放,形成了子进程的僵尸态,子进程的这种状态会一直持续,直到父进程也结束,系统才会完全回收子进程所占的内存空间。

你想想父亲还没嘎,儿子就先嘎。儿子有怨气,就尸变了。哈哈哈话糙理不糙,这个时候父亲要关怀一下儿子,儿子就可以无怨气的嘎了。

往往我们是不希望僵尸进程的出现,若一个父进程有多个子进程,这种情况将会导致内存一直被占用。我们希望的是创建的每一个子进程干完它的事就退出,不要对父进程或者其他进程有影响。wait函数就可以解决僵尸进程的回收问题。

二、wait函数

1.函数原型:pid_t wait(int *wstatus);

头文件  #include <sys/types.h>   #include <sys/wait.h>

参数:int *类型

返回值:pid_t类型

函数描述:man wait可以看到man手册对wait的主要描述

DESCRIPTION
       All of these system calls are used to wait for state changes in a child
       of the calling process, and obtain information about  the  child  whose
       state  has changed.

        If a child has already changed state, then these calls  return  immedi‐
       ately.   Otherwise,  they block until either a child changes state or a
       signal handler interrupts the call (assuming that system calls are  not
       automatically restarted using the SA_RESTART flag of sigaction(2)). 

RETURN VALUE
       wait():  on success, returns the process ID of the terminated child; on
       error, -1 is returned.
使用wait函数它会去检测子进程的退出状态,并将退出状态保存到wstatus。

如果在调用wait函数时没有子进程退出,那么wait函数将会阻塞父进程,直到有子进程结束或者有收到(signal)信号。如果进程本身没有子进程那么wait函数将立即返回。

wstatus状态检测

WIFEXITED(wstatus):检测子进程是否正常退出
WEXITSTATUS(wstatus):子进程正常退出,检测退出是以那种状态退出的
WIFSIGNALED(wstatus):检测是否是收到信号
WTERMSIG(wstatus):收到信号,检测信号是那种信号

例子:检测wait的触发是由子进程还是信号引起的

1.当不输入信号时,wait函数阻塞等待子进程结束,并将子进程的结束状态放入变量status中。此时子进程以0退出。结果如下:

2.当我们调整if的条件,让时间边长足够我们去输入信号

给进程输入SIGKILL信号

我们给子进程输入SIGKILL(9)信号,此时wait检测到SIGKILL(9)信号,结果如下:

当然,回收子进程的函数还有waitpid函数它比wait函数功能更强大,我们下次再来学希waitpid函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值