进程等待与终止

时间:2022-10-30 14:53:05
僵尸进程:一个子进程在其父进程没有调用wait()waitpid()的情况下退出。这个子进程就是僵尸进程。如果其父进程还存在而一直不调用wait,则该僵尸进程将无法回收,等到其父进程退出后该进程将被init回收。

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为 孤儿进程。孤儿进程将被 init 进程 ( 进程号为 1) 所收养,并由 init 进程对它们完成状态收集工 作。
******************************************************************************************************************************************************************
一、进程等待的函数 wait/waitpid
进程等待与终止
 
(1)wait 
参数:通过它拿到子进程的终止状态, 如果不关心 , 可将它设置为NULL,它是一个输出型参数。
           子进程的退出码:status的次八位(status>>8)&0xff, 也可以用宏 WEXITSTATUS(status) 查看;
            进程的终止情况:status的低八位(status&0xff),也可以用宏 WIFEXITED(status)查看; 当进程异常终止时,退出码无意义

返回值:成功->返回子进程的pid,失败->返回-1
功能:1、读取子进程退出状态;2、释放子进程的资源(PCB)

WEXITSTATUS(status)与 WIFEXITED(status) 宏解释:
WIFEXITED(status) : 1. 正常创建父子进程,子进程正常退出,父进程等待,并获取退出状 status 。调用该宏,查看输出结果(正常为非 0 ,或 1 )。 2. 正常创建父子进程,子进 pause() ,父进程等待,并设置获取退出状态 status kill 杀掉子进程,调用该宏,查看 输出结果(结果为 0 )。
WEXITSTATUS(status) : WIFEXITED 非零,返回子进程退出码,提取进程退 出返回值,如果子进程 exit(7),WEXITSTATUS(status) 就会返回 7. 请注意 , 如果进程不 是正常退出的 , 也就是说 ,WIFEXITED 返回 0, 这个值就毫无意义 .

(2) waitpid
返回值:1、 当正常返回的时候 waitpid 返回收集到的子进程的进程 ID
                2、如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0
                3、如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;
                4、当 pid 所指示的子进程不存在 , 或此进程存在 , 但不是调用进程的子进程 ,waitpid 会出错返回 , 这时 errno 被设置为ECHILD。                                                        
参数 pid : 1、p id=-1, 等待任 一个子进程。与 wait 等效。
    2、pid>0. 等待其进程 ID  为pid的子进程。
    3、pid==0 等待其组 ID 等于调用进程组 ID 的任一个子进程。
    4、pid<-1 等待其组 ID 等于 pid 绝对值的任一子进程。
           status: WIFEXITED(status) : 若为正常终止子进程返回的状态,则为真。(查看进程是 否是正常退出)
                       WEXITSTATUS(status) : WIFEXITED 非零,提取子进程退出码。(查看进程 的退出码)
           options:1、 WNOHANG : pid 指定的子进程没有结束,则 waitpid() 函数返回 0 ,调用waitpid的进程不会被阻塞,将继续执 行; 若正常结束,则返回该子进程的 ID
                        2、  options==0: 调用waitpid的进程会进行阻塞等待。
waiptpid提供了wait没有提供的三个功能:
1. waitpid 可等待一个特定的进程
2. waitpid 提供了一个 wait 的非阻塞版本
3. waitpid 支持作业控制

waitpid的使用例子
子进程的执行流:(若不说明退出方式,它的退出方式默认为exit(0))
进程等待与终止
父进程的执行流:(因为是以非阻塞的方式等待子进程,在子进程没有退出时,waitpid的返回值一直都是0,所以要以循环的方式等待,直到waitpid的返回值为子进程的ID时,才等待成功)
进程等待与终止

******************************************************************************************************************************************************************
二、进程终止
(1) 进程终止的方式有 8 种,前 5 种为正常终止,后三种为异常终止:
1 main 函数返回;
2 调用 exit 函数;
3 调用 _exit _Exit
4 最后一个线程从启动例程返回;
5 后一个线程调用 pthread_exit
6 调用 abort 函数;
7 接到一个信号并终止;
8 最后一个线程对取消请求做出响应。
(2)exit与 _Exit,_exit的区别
          _exit _Exit 立即进入内核,而 exit 则要先做一些清理 工作(调用执行各终止处理程序,关闭所有标准 I/O 流),再进入内核。
#include <stdlib.h>
void exit( int status );
void _Exit( int status );
#include <unistd.h>
void _exit( int status );
这三个函数用于正常终止一个程序, 三个函数所带的整 型参数称为终止状态或退出状态,如果
a )调用这些函数不带参数;
b main 函数中的 return 语句无返回值;
c main 函数没有声明返回类型为整型; 则进程的终止状态是未定义 的。

main 函数返回一个整型值与用该值调用 exit 是等价的。