Chinaunix首页 | 论坛 | 博客
  • 博客访问: 299009
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: LINUX

2009-03-05 21:34:43

这篇文章将展示最常用的进程函数fork,wait,waitpid等。
fork函数对当前进程进行复制,调用一次,返回两个值,在父进程中返回子进程的进程号,在进程中返回0,当然调用失败时返回-1.为啥父进程返回子进程号呢,因为在子进程中可以通过getppid()函数来获取父进程号,而父进程却没有获取子进程号的途径。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    pid_t pid;
    char *message;
    int n;

    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;
        break;
    default:
        message = "This is the parent";
        n = 3;
        break;
    }

    for(; n > 0; n--) {
    printf("%s ",message);
    printf(" pid is %d ppid is %d \n",getpid(),getppid());
        sleep(1);
    }
    exit(0);
}

程序运行结果为
fork program starting
This is the child    pid is 8381   ppid is 8380
This is the parent    pid is 8380   ppid is 7689
This is the child    pid is 8381   ppid is 8380
This is the parent    pid is 8380   ppid is 7689
This is the child    pid is 8381   ppid is 8380
This is the parent    pid is 8380   ppid is 7689
This is the child    pid is 8381   ppid is 8380
[root@localhost]# This is the child    pid is 8381   ppid is 1

可以看到,父进程先于子进程结束,在父进程结束后,子进程ppid变为1,被init进程收养。

我们可以让父进程等待子进程,用到wait函数,函数原型为:
pid_t wait(int *status);
在上面程序最后的for循环和exit(0)之间加入如下代码

if(pid) {
        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");

    }
运行结果为
This is the child    pid is 8639   ppid is 8638
This is the parent    pid is 8638   ppid is 7689
This is the child    pid is 8639   ppid is 8638
This is the parent    pid is 8638   ppid is 7689
This is the child    pid is 8639   ppid is 8638
This is the parent    pid is 8638   ppid is 7689
This is the child    pid is 8639   ppid is 8638
This is the child    pid is 8639   ppid is 8638
Child has finished: PID = 8639
Child exited with code 0
[root@localhost]#

父进程在完成自己的代码后,并没有退回到shell(shell提示符出现在最后,子进程结束后),而是等待子进程的结束,子进程的ppid一直都是父进程的pid。

如果子进程先于父进程结束,那么它会变为一个僵进程,用ps命令可在其后见到,下面为子进程结束后,父进程仍在运行时的ps命令输出。
root      8712  7689  0 21:49 pts/1    00:00:00 ./f1
root      8713  8712  0 21:49 pts/1    00:00:00 [f1]

等待函数wait将使父进程阻塞,一直等到有子进程结束为止,当父进程还有很多的工作要做时,这样显得效率非常低下,这时可以使用waitpid函数,指定WNOHANG标志,可使父进程不阻塞。

pid_t waitpid(pid_t pid, int *status, int options);
第一个参数为要等待的子进程pid,为-1时,将等待任一子进程。
waitpid():成功执行时,返回状态改变的子进程标识。失败返回-1;如果指定WNOHANG标志,同时pid指定的进程状态没有发生变化,将返回0。
waitpid的好处是父进程可以周期性的检查某子进程的状态,而不用阻塞在调用处。

waitpid提供了wait所没有的三个特性:
1 waitpid使我们可以等待指定的进程
2 waitpid提供了一个无阻塞的wait
3 waitpid支持工作控制


阅读(1889) | 评论(2) | 转发(4) |
给主人留下些什么吧!~~

chinaunix网友2010-09-13 22:21:28

[而父进程却没有获取子进程号的途径] 这句有些错误 , 当父进程 fork 后 child_pid 返回的正是子进程的进程号

chinaunix网友2010-03-04 11:01:41

不错,适合入门参考 。看apu中的相应部分,看累了,看看你的文档,有点收获。