进程控制之函数wait、waitpid、waitid、wait3和wait4

函数wait和waitpid

调用waitwaitpid函数进程会发生什么。

  1. 如果其所有子进程都还在运行,则阻塞。
  2. 如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回。
  3. 如果它没有任何子进程,则立即出错返回。
#include <sys/wait.h>
pid_t wait(int *statloc);
pif_t waitpid(pid_t pid, int *statloc, int options);
两个函数返回值:若成功,返回进程ID;若出错,返回0-1

两个函数的区别如下:

  1. 在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项,可使调用者不阻塞。
  2. waitpid并不等待在其调用之后的第一个终止子进程,它由若干个选项,可以控制它所等待的进程。

POSIX.1 规定,终止状态用定义在<sys/wait.h>中的各个宏来查看,

说明
WIFEXITED(status)若为正常终止子进程返回的状态,则为真。对于这种情况可执行WEXITSTATUS(status),获取子进程传送给exit_exit的参数的低8位。
WIFSIGNALED(status)若为异常终止子进程返回的状态,则为真。对于这种情况,可执行WTERMSIG(status),获取使子进程终止的信号编号。另外,有些实现定义宏WCOREDUMP(status),若已产生终止进程的core文件,则它返回真。
WIFSTOPPED(status)若为当前暂停子进程的返回的状态,则为真。对于这种情况,可执行WSTOPSIG(status),获取使子进程暂停的信号编号。
WIFCONTINUED(status)若在作业控制暂停后已经继续的子进程返回了状态,则为真。

测试示例:

#include "../../include/apue.h"
#include <sys/wait.h>
void pr_exit(int status)
{
    if(WIFEXITED(status))
        printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
    else if(WIFSIGNALED(status))
        printf("abnormal termination, signal number = %d%s\n", 
               WTERMSIG(status),
#ifdef WCOREDUMP
               WCOREDUMP(status) ? "(core file generated)" : "");
#else
                "");
#endif
        else if(WIFSTOPPED(status))
            printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
int main(void)
{
    pid_t pid;
    int status;

    if((pid = fork()) < 0)
        err_sys("fork error");
    else if(pid == 0)
        exit(7);

    if(wait(&status) != pid)
        err_sys("wait error");
    pr_exit(status);

    if((pid = fork()) < 0)
        err_sys("fork error");
    else if (pid == 0)
        abort();

    if(wait(&status) != pid)
        err_sys("wait error");
    pr_exit(status);

    if((pid = fork()) < 0)
        err_sys("fork error");
    else if (pid == 0)
        status /= 0;

    if(wait(&status) != pid)
        err_sys("wait error");
    pr_exit(status);
    return 0;
}

结果如下:

这里给出相应信号所代表的值。

对于waitpid函数中pid参数的作用如下:

pid == -1 等待任一子进程。此种情况下,waitpidwait等效。

pid > 0 等待进程ID与pid相等的子进程。

pid == 0 等待组进程ID等于调用进程组ID的任一子进程。

pid < -1 等待组ID等于pid绝对值的任一子进程。

options参数是如下常量按位或运算的结果。

常量说明
WCONTINUED若实现支持作业控制,那么由pid指定的任一子进程在停止后已经继续,但其状态尚未报告,则返回其状态。
WNOHANG若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回值为0。
WUNTRACED若某实现支持作业控制,而由pid指定的任一子进程已处于停止状态,并且其状态自停止以来还未报告过,则返回其状态。WIFSTOPPED宏确定返回值是否对应于一个停止的子进程。

waitpid函数提供了wait函数没有提供的3个功能。

  1. waitpid可等待一个特定进程,而wait则返回任一终止子进程。
  2. waitpid提供了一个wait的非阻塞版本。
  3. waitpid通过WUNTRACED和WCONTINUED选项支持作业控制。

测试示例:

如果一个进程fork一个进程,但不要它等待子进程终止,也不希望子进程处于僵尸状态直到父进程终止。

#include "../../include/apue.h"
#include <sys/wait.h>

int main(void)
{
    pid_t pid;
    if((pid=fork()) < 0){
        err_sys("fork error");
    }else if(pid == 0)
    {
        if((pid = fork()) < 0)
            err_sys("fork error");
        else if(pid > 0){
                sleep(1);
                printf("second pid = %ld\n", (long)pid);
                exit(0);
        }
        
        printf("second ppid = %ld\n", (long)getppid());
        sleep(2);
        printf("second child, parent pid = %ld, pid = %ld\n", 
               (long)getppid(), (long)getpid());
        exit(0);
    }

    if(waitpid(pid, NULL, 0) != pid)
        err_sys("waitpid error");
    printf("first pid = %ld\n", (long)pid);
    return 0;
}

结果如下:

由上图可知,我们通过打印进程ID,得知第二个子进程等待其父进程(即第一个子进程)终止后,会被init进程所接受并处理。

函数waitid

另一个取得进程终止状态的函数——waitid。此函数类似于waitpid函数。

#include <sys/wait.h>
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
返回值:若成功,返回0;若出错,返回-1

idtype参数的取值与id参数相关。

常量说明
P_PID等待一特定进程:id包含要等待子进程的进程ID
P_PGID等待一特定进程组中的任一子进程:id包含要等待子进程的进程组ID
P_ALL等待任一子进程:忽略id

options参数是如下标志的按位或运算,这些标志指示调用者关注哪些状态变化。

常量说明
WCONTINUED等待一进程,它以前曾被停止,此后又已继续,但其状态尚未报告
WEXITED等待已退出的进程
WNOWAIT不破坏子进程退出状态。该进程退出状态可由后续的waitwaitidwaitpid调用取得
WNOHANG如无可用的子进程退出状态,立即返回而非阻塞
WSTOPPED等待一进程,它已经停止,但其状态尚未报告

函数wait3wait4

函数wait3wait4与函数waitwaitpid以及waitid函数功能相似,但是多了一个允许内核返回终止进程及其所有子进程使用的资源概况参数(资源统计信息包括用户CPU时间总量、系统CPU时间总量、缺页次数、接收到信号的次数等)。

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
pid_t wait3(int *statloc, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage);
两个函数返回值:若成功,返回进程ID;若出错,返回-1
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值