LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 999|回复: 10

[提问]关于fork()

[复制链接]
发表于 2007-7-13 11:06:14 | 显示全部楼层 |阅读模式
  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <time.h>

  5. int main()
  6. {
  7.         pid_t pid_1;
  8.         pid_t pid_2;

  9.         pid_1 = fork();
  10.         pid_2 = fork();

  11.         if (pid_1 < 0 || pid_2 < 0)
  12.         {
  13.                 printf("erro_fork\n");
  14.                 exit(1);
  15.         }
  16.         else if (pid_1 == 0)
  17.         {
  18.                 sleep(5);
  19.                 printf("pid_1 = %d\n", getpid());
  20.                 _exit;
  21.         }
  22.         else if (pid_2 == 0)
  23.         {
  24.                 sleep(3);
  25.                 printf("pid_2 = %d\n", getpid());
  26.                 _exit;
  27.         }
  28.         else
  29.         {
  30.                 sleep(6);
  31.                 printf("pid_parrent = %d\n", getpid());
  32.         }

  33.         return 0;
  34. }
复制代码


运行结果:

  1. pid_2 = 8162
  2. pid_1 = 8161
  3. pid_1 = 8160
  4. pid_parrent = 8159
复制代码


为什么会有两个pid_1呢?

fork()函数可以这样用吗?……看了APUE2还是不太理解这个函数的调用……
发表于 2007-7-13 11:39:55 | 显示全部楼层
原因是这样的,pid_2被fork了两次,所以pid2执行了两次,pid_2在执行的时候也发现pid_1==0,所以再次执行了pid_1=的打印信息。
  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. int main()
  6. {
  7.         pid_t pid_1;
  8.         pid_t pid_2;
  9.         pid_1 = fork();
  10.         pid_2 = fork();
  11.         if (pid_1 < 0 || pid_2 < 0)
  12.         {
  13.                 printf("erro_fork\n");
  14.                 exit(1);
  15.         }
  16.         else if (pid_2 == 0)
  17.         {
  18.                 sleep(3);
  19.                 printf("pid_2 = %d\n", getpid());
  20.                 _exit;
  21.         }
  22.         else if (pid_1 == 0)
  23.         {
  24.                 sleep(5);
  25.                 printf("pid_1 = %d\n", getpid());
  26.                 _exit;
  27.         }
  28.         else
  29.         {
  30.                 sleep(6);
  31.                 printf("pid_parrent = %d\n", getpid());
  32.         }
  33.         return 0;
  34. }
复制代码
代码这样写,你再看看结果,就明白了。
回复 支持 反对

使用道具 举报

发表于 2007-7-13 11:57:39 | 显示全部楼层
这个程序其实分成了四个进程。
第一步,fork之后,parent process中pid_1 = child pid,child process中的pid_1 = 0;
第二步fork(),以上的两个进程都再派生出一个新的进程,在这些新fork出的的子进程中pid_2 = 0
  1.                        +------------------+
  2.                        |        main      |
  3.                        +---------+--------+
  4.                                   |pid_1=fork()
  5.                    +--------------+-------------------+
  6.                    |                                  |
  7.             +------+----------+             +---------+--------+
  8.             | parent          |             |      child       |
  9.             | pid_1 = ?       |             |   pid_1 = 0      |
  10.             +-------+---------+             +---------+--------+
  11.                     | pid_2 = fork()                  |pid_2 = fork()
  12.             +-------+--------+              +---------+---------+
  13.             |                |              |                   |
  14.   +---------+-------+ +------+------+ +-----+------+     +------+------+
  15.   | parent          | | child       | | parent     |     |   child     |
  16.   |pid_1 = ?        | | pid_1 = ?   | | pid_1 = 0  |     | pid_1 = 0   |
  17.   |pid_2 = ?        | | pid_2 = 0   | | pid_2 = ?  |     | pid_2 = 0   |
  18.   +-----------------+ +-------------+ +------------+     +-------------+
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-13 12:02:57 | 显示全部楼层
还是不太明白,为什么pid_2 会被fork两次呢?

如过,我想fork许多进程,是不是就不应该这样写代码啊?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-13 12:08:57 | 显示全部楼层
这个程序其实分成了四个进程。
第一步,fork之后,parent process中pid_1 = child pid,child process中的pid_1 = 0;
第二步fork(),以上的两个进程都再派生出一个新的进程,在这些新fork出的的子进程中pid_2 = 0

我稍微明白了你说的意思,你是不是说,pid_2 即是父进程的子进程,也是pid_1的子进程?

所以执行了两次

这样的话就不是我想完成的目的了T_T

如果,我希望一个父进程fork许多子进程,那应该怎么做呢?
回复 支持 反对

使用道具 举报

发表于 2007-7-13 12:19:55 | 显示全部楼层
Post by sunorr
我稍微明白了你说的意思,你是不是说,pid_2 即是父进程的子进程,也是pid_1的子进程?

所以执行了两次

这样的话就不是我想完成的目的了T_T

如果,我希望一个父进程fork许多子进程,那应该怎么做呢?

我想我的那个图应该很明白了吧?
你可以这么做

  1. #define NCHILD 10
  2. pid_t  pids[NCHILD];
  3. int i = 0;
  4. do{
  5.         pid_t pid = fork();
  6.         if(pid == 0) break;
  7.         pids[i++] = pid;
  8. }while(i < NCHILD);

复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-13 13:24:20 | 显示全部楼层
我想我的那个图应该很明白了吧?

恩,恩,我想,我可以明白你的图,可是,为什么按照我写的东西,为什么会产生那样的效果?

对fork的工作机理还是晕晕的……
  1. if(pid == 0) break;
复制代码

看到你写的代码,我感觉是,子进程如果创建后,是不是就基本上脱离父进程了?

不知道我感觉的对不对?

呵呵,真的要谢谢版主和你~
回复 支持 反对

使用道具 举报

发表于 2007-7-13 14:40:17 | 显示全部楼层
Post by sunorr
恩,恩,我想,我可以明白你的图,可是,为什么按照我写的东西,为什么会产生那样的效果?
有没有看到最后的四个进程中,有两个进程的pid_1 = 0?,这就是为什么会有两个输出的原因。每个进程都输出一个。
Post by sunorr

对fork的工作机理还是晕晕的……
  1. if(pid == 0) break;
复制代码

看到你写的代码,我感觉是,子进程如果创建后,是不是就基本上脱离父进程了?

不知道我感觉的对不对?

呵呵,真的要谢谢版主和你~
简单地说,fork()之后,就会产生两个几乎相同(相同的内存镜像、文件描述符等)的进程。然后这两个进程都紧接着fork()继续运行。
在不涉及到进程管理的阶层上,你可以认为他们两个是独立的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-13 16:49:57 | 显示全部楼层
简单地说,fork()之后,就会产生两个几乎相同(相同的内存镜像、文件描述符等)的进程。然后这两个进程都紧接着fork()继续运行。
在不涉及到进程管理的阶层上,你可以认为他们两个是独立的。

恩,恩,明白些了,那也就是说,我也可以在fork()子进程以后在子进程中添加父进程没有的功

能了。

关于进程管理方面,感觉APUE2讲的我还能看懂些,呵呵
回复 支持 反对

使用道具 举报

发表于 2007-7-14 01:30:44 | 显示全部楼层
Post by sunorr
恩,恩,明白些了,那也就是说,我也可以在fork()子进程以后在子进程中添加父进程没有的功能了。

这是当然了,这就是为什么你会看到很多程序都会这样写

  1. if(fork() == 0){
  2.     /*child process */
  3. }else{
  4.     /*parent process */
  5. }
复制代码

就是说通过fork()的返回值你完全可以将父进程和子进程切分出来。所以,你完全可以单独决定他们该干什么。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表