zoukankan      html  css  js  c++  java
  • linux 之进程基础 (六)、进程API之进程资源回收函数

    6. 进程API之进程资源回收函数

    6.1 wait函数和waitpid函数 简介

    6.1.1 wait函数

    调用该函数使进程阻塞,直到任一个子进程结束或者是该进程接收到了一个信号为止。如果该进程没有子进程或者其子进程已经结束,wait函数会立即返回。

    此时父进程属于可中断状态

    6.1.2waitpid函数

    功能和wait函数类似。可以指定等待某个子进程结束以及等待的方式(阻塞或非阻塞,由参数指定阻塞还是不阻塞.)。事实上wait()函数只是waitpid()函数的特例,内部实现wait()函数时,直接调用waitpid()。

    6.2 wait函数

    6.2.1 wait 函数原型

    #include <sys/types.h>
    #include <sys/waith.h>
    
    pid_t  wait(int  *status);
    

    6.2.2 wait函数参数和返回值

    6.2.2.1函数参数:
    status是一个整型指针,指向的对象用来保存子进程退出时的状态。

    • A.status若为空
      表示忽略子进程退出时的状态 实际上回收了 但是不想看这个值是多少了
    • B.status若不为空

    为什么需要一个status 指针 作为参数呢?
    父进程要获取子进程的退出状态,需要在父进程中有一个位置来存储子进程的退出状态,因此需要在父进程中定义一个int型的指针变量传递给wait函数。

    6.2.2.2 返回值

    • 成功
      返回已经回收的子进程的pid

    • 失败
      返回-1

    6.3 waitpid函数

    6.3.1 waitpid函数原型

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

    6.3.2 waitpid 函数参数

    (1)参数为pid,有一下选项:

    • pid > 0:回收进程ID等于pid的子进程 即回收指定子进程
    • pid = -1:回收任何一个子进程,此时和wait作用一样
    • pid = 0 : 回收其组ID等于调用进程的组ID的任一子进程
    • 和调用进程 组id号(即:同一进程组)相同的任何一个id
    • pid < -1: 回收其组ID等于pid 绝对值的任一子进程 此时pid 填的是进程组id
      例如填 -7844 就可以回收7844 进程组中的任一进程

    (2)status:

    • 同wait函数。

    (3)options:

    • WNOHANG,若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0 假如需要等待的子进程属于睡眠状态,此时,父进程不等待子进程,而是立刻返回
    • WUNTRACED,若某实现作业控制操作,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还没报告过,则返回其状态。(一般不会用这个参数。)
    • 0:同wait,阻塞父进程,等待子进程退出。

    6.3.3 waitpid函数返回值

    • 正常:结束的子进程的进程号
    • 使用选项WNOHANG且没有子进程结束时:0
    • 调用出错:-1

    6.4 清除僵尸进程

    6.4.1 如何清除僵尸? 三种方式

    • 父进程提前退出
    • 真父委托继父
    • 真父wait(真父回收)

    6.4.2 三种方式介绍

    • 子进程在退出的过程中,内核会给其父进程发送一个信号,通知父进程来“收尸”。这个信号默认是SIGCHLD。如果父进程通过等待他(调用wait/ waitpid)回收了这个僵尸进程,那么内核就会立即释放掉task_struct,即僵尸很快就被清理了。
    • 父进程在创建子进程之前通知内核不想等待回收他,则内核在子进程结束后内核直接将子进程的僵尸回收掉。在Linux下 可以简单地将SIGCHLD信号的操作设为SIG_IGN。signal(SIGCHLD,SIG_IGN);通知涉及信号,在信号处理时再讲。
    • 如果子进程的父进程在子进程没有结束之前先结束了,那么该进程就不会变成僵尸进程,因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程, 看有没有哪个进程是刚刚结束的这个进程的子进程,如果是的话,就由Init来接管他,成为他的父进程……。)而init成为子进程的继父进程后就会在其结束时负责清理它。
      注意:
      linux系统启动后,第一个被创建的用户态进程就是init进程。它有两项使命:
      1、执行系统初始化脚本,创建一系列的进程(它们都是init进程的子孙);
      2、在一个死循环中等待其子进程的退出事件,并调用waitid系统调用来完成“收尸”工作;init进程不会被暂停、也不会被杀死(这是由内核来保证的)。它在等待子进程退出的过程中处于TASK_INTERRUPTIBLE状态,“收尸”过程中则处于TASK_RUNNING状态。)
  • 相关阅读:
    [COCI2013]DLAKAVAC
    [TJOI2013]最长上升子序列
    AGC040E Prefix Suffix Addition
    AGC010E Rearranging
    AGC021F Trinity
    AGC002F Leftmost Ball
    JOISC2019D ふたつのアンテナ
    LOJ6210 「美团 CodeM 决赛」tree
    Luogu P3781 [SDOI2017]切树游戏
    Problem. M
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764128.html
Copyright © 2011-2022 走看看