ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 进程与信号(三)

进程与信号(三)

原创 Linux操作系统 作者:mylxiaoyi 时间:2009-08-10 19:16:00 0 删除 编辑

等待一个进程

当我们使用fork启动一个子进程时,他具有其自己的生命周期并且独立运行。有时,我们希望知道一个子进程何时结束。例如,在前一个例子中,父进程在子进程之前结束,从而我们得到混乱的输出,因为子进程还在继续运行。我们可以通过调用wait来使得父进程在继续运行之前等待,直到子进程结束。

#include
#include
pid_t wait(int *stat_loc);

wait系统调用暂停父进程,直到他的一个子进程结束。这个函数调用返回其子进程的PID。这通常是一个已经结束的子进程。状态信息使得父进程可以确定子进程的结束状态,也就是,由main返回或是传递给exit的值。如果stat_loc不是一个空指针,状态信息就会被写入他所指向的地址。

我们可以使用定义在sys/wait.h中的宏来解释这些状态信息。这个宏包括:

宏 定义
WIFEXITED(stat_val) 如果子进程正常结束为非0
WEXITSTATUS(stat_val) 如果WIFEXITED为非0,这会返回子进程的结束代码
WIFSIGNALED(stat_val) 如果子进程是因为一个未捕获的信号而结束的,则为非0
WTERMSIG(stat_val) 如果WIFSIGNALED为非0,这会返回一个信号编号
WIFSTOPPED(stat_val) 如果子进程已经结束则为非0
WSTOPSIG(stat_val) 如果WIFSTOPPED为非0,这会返回一个信号编号

试验--wait

让我们来简单的修改一下我们的程序,从而我们可以等待并且检测子进程的结束状态。我们将其命名为wait.c。

#include
#include
#include
#include
int main()
{
pid_t pid;
char *message;
int n;
int exit_code;
printf(“fork program starting\n”);
pid = fork();
switch(pid)
{
case -1:
perror(“fork failed”);
exit(1);
case 0:
message = “This is the child”;
n = 5;
exit_code = 37;
break;
default:
message = “This is the parent”;
n = 3;
exit_code = 0;
break;
}
for(; n > 0; n--) {
puts(message);
sleep(1);
}

下面的程序部分等待子进程结束。

if (pid != 0) {
int stat_val;
pid_t child_pid;
child_pid = wait(&stat_val);
printf(“Child has finished: PID = %d\n”, child_pid);
if(WIFEXITED(stat_val))
printf(“Child exited with code %d\n”, WEXITSTATUS(stat_val));
else
printf(“Child terminated abnormally\n”);
}
exit(exit_code);
}

如果我们运行这个程序,我们就会看到父进程等待子进程。

$ ./wait
fork program starting
This is the child
This is the parent
This is the parent
This is the child
This is the parent
This is the child
This is the child
This is the child
Child has finished: PID = 1582
Child exited with code 37
$

工作原理

父进程由fork调用中得到一个返回的非0值,他使用wait系统调用挂起其自己的运行子进程的状态信息变得可用为止。这会在子进程调用exit时发生,我们为其指定一个返回代码37。然后父进程继续执行,通过检测wait调用所返回的值确定子进程正常结束,然后由状态信息解出结束代码。

僵尸进程

使用fork创建进程非常有用,但是我们必须跟踪子进程。当一个子进程结束时,他与其父进程的关联依然存在,直到父进程正常结束或是调用wait。进程中的子进程实体因而并没有立即释放。尽管已经不再是活动状态,子进程仍然存在于系统当中,因为需要存储退出代码,以防止父进程调用wait函数。他就变成所谓的死亡状态,或是一个僵尸进程。

如果我们在上面的fork示例程序中改变消息数量,我们就可以看到僵尸进程的创建。如果子进程输出的消息少于父进程,那么就会首先结束,并且退出成为一个僵尸进程,直到其父进程结束。

试验--僵尸进程

fork2.c与fork1.c相类似,所不同的是子进程所输出的消息数量,而父进程所输出的消息数量不变。下面是相关的代码:

switch(pid)
{
case -1:
perror(“fork failed”);
exit(1);
case 0:
message = “This is the child”;
n = 3;
break;
default:
message = “This is the parent”;
n = 5;
break;
}

工作原理

如果我们使用命令./fork2 &来运行上面的程序,并且在子进程结束之后父进程结束之前调用ps程序,我们就可以看到如下的输出(一些系统也许会称之为而不是)。

$ ps

Link URL: http://mylxiaoyi.javaeye.com/blog/404318

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/13670711/viewspace-611808/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-07-09

  • 博文量
    25
  • 访问量
    11044