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状态。)
  • 相关阅读:
    ios 数据类型转换 UIImage转换为NSData NSData转换为NSString
    iOS UI 12 block传值
    iOS UI 11 单例
    iOS UI 08 uitableview 自定义cell
    iOS UI 07 uitableviewi3
    iOS UI 07 uitableviewi2
    iOS UI 07 uitableview
    iOS UI 05 传值
    iOS UI 04 轨道和动画
    iOS UI 03 事件和手势
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764128.html
Copyright © 2011-2022 走看看