【归纳整理】Liunx下的进程管理(三),多进程的等待和终止

进程的正常退出
------------------


1. 从main函数中return。


int main (...) {
    ...
    return x;
}


等价于:


int main (...) {
    ...
    exit (x);
}


2. 调用标准C语言的exit函数。


#include <stdlib.h>


void exit (int status);


1) 调用进程退出,
   其父进程调用wait/waitpid函数返回status的低8位。


2) 进程退出之前,
   先调用所有事先通过atexit/on_exit函数注册的函数,
   冲刷并关闭所有仍处于打开状态的标准I/O流,
   删除所有通过tmpfile函数创建的文件。


#include <stdlib.h>


int atexit (void (*function) (void));


function - 函数指针,
           指向进程退出前需要被调用的函数。
           该函数既没有返回值也没有参数。


成功返回0,失败返回非零。


int on_exit (void (*function) (int, void*), void* arg);


function - 函数指针,
           指向进程退出前需要被调用的函数。
           该函数没有返回值但有两个参数:
           第一参数来自exit函数的status参数,
           第二个参数来自on_exit函数的arg参数。


arg      - 任意指针,
           将作为第二个参数被传递给function所指向的函数。


成功返回0,失败返回非零。


3) 用EXIT_SUCCESS/EXIT_FAILURE常量宏
   (可能是0/1)作参数,调用exit()函数表示成功/失败,
   提高平台兼容性。


4) 该函数不会返回。


5) 该函数的实现调用了_exit/_Exit函数。


3. 调用_exit/_Exit函数。


#include <unistd.h>


void _exit (int status);


1) 调用进程退出,
   其父进程调用wait/waitpid函数返回status的低8位。


2) 进程退出之前,
   先关闭所有仍处于打开状态的文件描述符,
   将其所有子进程托付给init进程(PID为1的进程)收养,
   向父进程递送SIGCHILD信号。


3) 该函数不会返回。


4) 该函数有一个完全等价的标准C版本:


#include <stdlib.h>


void _Exit (int status);


4. 进程的最后一个线程执行了返回语句。


5. 进程的最后一个线程调用pthread_exit函数。






进程的异常终止
------------------


1. 调用abort函数,产生SIGABRT信号。


2. 进程接收到某些信号。


3. 最后一个线程对“取消”请求做出响应。


wait/waitpid
----------------


等待子进程终止并获取其终止状态。


#include <sys/types.h>
#include <sys/wait.h>


pid_t wait (int* status);


pid_t waitpid (pid_t pid, int* status, int options);


成功返回终止子进程的PID,失败返回-1。


1. 当一个进程正常或异常终止时,
   内核向其父进程发送SIGCHLD信号。
   父进程可以忽略该信号,
   或者提供一个针对该信号的信号处理函数,默认为忽略。


2. 父进程调用wait函数:


1) 若所有子进程都在运行,则阻塞。


2) 若有一个子进程已终止,
   则返回该子进程的PID和终止状态(通过status参数)。


3) 若没有需要等待子进程,则返回失败,errno为ECHILD。


3. 在任何一个子进程终止前,wait函数只能阻塞调用进程,
   而waitpid函数可以有更多选择。


4. 如果有一个子进程在wait函数被调用之前,
   已经终止并处于僵尸状态,wait函数会立即返回,
   并取得该子进程的终止状态。


5. 子进程的终止状态通过输出参数status返回给调用者,
   若不关心终止状态,可将此参数置空。


6. 子进程的终止状态可借助
   sys/wait.h中定义的参数宏查看:


WIFEXITED(): 子进程是否正常终止,
是则通过WEXITSTATUS()宏,
获取子进程调用exit/_exit/_Exit函数,
所传递参数的低8位。
因此传给exit/_exit/_Exit函数的参数最好不要超过255。


WIFSIGNALED(): 子进程是否异常终止,
是则通过WTERMSIG()宏获取终止子进程的信号。


WIFSTOPPED(): 子进程是否处于暂停,
是则通过WSTOPSIG()宏获取暂停子进程的信号。


WIFCONTINUED(): 子进程是否在暂停之后继续运行



7. 如果同时存在多个子进程,又需要等待特定的子进程,
   可使用waitpid函数,其pid参数:


 -1 - 等待任一子进程,与wait函数等价;
 >0 - 等待特定子进程(由pid参数标识);
  0 - 等待与调用进程同进程组的任一子进程;
<-1 - 等待特定进程组(由pid参数的绝对值标识)的任一子进程。



8. waitpid函数的options参数可取0(忽略)或以下值的位或:


WNOHANG    - 非阻塞模式,
             若没有可用的子进程状态,则返回0。


WUNTRACED  - 若支持作业控制,且子进程处于暂停态,
             则返回其状态。


WCONTINUED - 若支持作业控制,且子进程暂停后继续,
             则返回其状态。



八、exec
--------


1. exec函数会用新进程完全替代调用进程,
   并开始从main函数执行。


2. exec函数并非创建子进程,新进程取调用进程的PID。


3. exec函数所创建的新进程,
   完全取代调用进程的代码段、数据段和堆栈段。


4. exec函数若执行成功,则不会返回,否则返回-1。


5. exec函数包括六种形式:


#include <unistd.h>


int execl  (
    const char* path,
    const char* arg,
    ...
);


int execv  (
    const char* path,
    char* const argv[]
);


int execle (
    const char* path,
    const char* arg,
    ...,
    char* const envp[]
);


int execve (
    const char* path,
    char* const argv[],
    char* const envp[]
);


int execlp (
    const char* file,
    const char* arg,
    ...
);


int execvp (
    const char* file,
    char* const argv[]
);


l: 新程序的命令参数以单独字符串指针的形式传入
   (const char* arg, ...),参数表以空指针结束。


v: 新程序的命令参数以字符串指针数组的形式传入
   (char* const argv[]),数组以空指针结束。


e: 新程序的环境变量以字符串指针数组的形式传入
   (char* const envp[]),数组以空指针结束,
   无e则从调用进程的environ变量中复制。


p: 若第一个参数中不包含“/”,则将其视为文件名,
   根据PATH环境变量搜索该文件。






system
----------


#include <stdlib.h>


int system (const char* command);


1. 标准C函数。执行command,
   成功返回command对应进程的终止状态,失败返回-1。


2. 若command取NULL,返回非零表示shell可用,
   返回0表示shell不可用。


3. 该函数的实现,
   调用了vfork、exec和waitpid等函数,
   其返回值:


1) 如果调用vfork或waitpid函数出错,则返回-1。


2) 如果调用exec函数出错,则在子进程中执行exit(127)。


3) 如果都成功,则返回command对应进程的终止状态
   (由waitpid的status输出参数获得)。


4. 使用system函数而不用vfork+exec的好处是,

   system函数针对各种错误和信号都做了必要的处理。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值