加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

fork() && fork() || fork();

(2012-05-01 12:58:49)
标签:

it

哪天chinaunix看帖子,看到一个有趣的题目,今天思考了下,记录一下。
int main(int argc, char* argv[])
{
   fork();
   fork() && fork() || fork();
   fork();
}
不算main这个进程自身,到底创建了多少个进程啊?

分析:

1. 第一个fork(), 第五个fork(), 肯定会执行,故总进程数= 2 * (fork() && fork() || fork()) *2 

2. 关键就是fork2() && fork3() || fork4() 产生来了多少个进程

   每个fork()返回值要么等于0,要么大于0(c语言中无bool,非0在逻辑运算中即是1)

   我已经把fork() 24标号。

   执行用伪代码表示,逻辑如下:

   if(fork2 返回> 0)

   {

       if(fork3 返回> 0)

                     //1个进程

       else(fork3 返回 == 0)

           fork4 //2个进程

   }

   else

   {

          fork4//2个进程

    }

所以共计 2*5*2 -1 = 19个进程。





#include <unistd.h>
#include <stdio.h>

int main()
{
        fork();

        fork() && fork() || fork();

        fork();

        sleep(100);

        return 0;
}
     据说是EMC的一道选择题,感觉挺有意思的,这道题主要考了两个知识点,一是逻辑运算符运行的特点;二是对fork的理解。这道题在Linux(Ubuntu 9.10)输出如下:
ecy@ecy-geek:~/C++$ ps
  PID TTY          TIME CMD
 1833 pts/0    00:00:00 bash
 2088 pts/0    00:00:00 fork
 2089 pts/0    00:00:00 fork
 2090 pts/0    00:00:00 fork
 2091 pts/0    00:00:00 fork
 2092 pts/0    00:00:00 fork
 2093 pts/0    00:00:00 fork
 2094 pts/0    00:00:00 fork
 2095 pts/0    00:00:00 fork
 2096 pts/0    00:00:00 fork
 2097 pts/0    00:00:00 fork
 2098 pts/0    00:00:00 fork
 2099 pts/0    00:00:00 fork
 2100 pts/0    00:00:00 fork
 2101 pts/0    00:00:00 fork
 2102 pts/0    00:00:00 fork
 2103 pts/0    00:00:00 fork
 2104 pts/0    00:00:00 fork
 2105 pts/0    00:00:00 fork
 2106 pts/0    00:00:00 fork
 2107 pts/0    00:00:00 fork
 2108 pts/0    00:00:00 ps
       从2088到2107这20个进程,除了一个主进程,其余19个进程都是fork出来的。刚开始我看到这个结果感觉有点奇怪,接着在纸上分析了一下,算得 头都晕了,最后才算出正确值来了。恩,使用二叉树画图分析是比较好的方法。现在我想通过等价的方法改写上面的代码,使之更易懂。
      如果有一个这样的表达式:
cond1 && cond2 || cond3
      这句代码会怎样执行呢?首先看一个例子,代码如下:
#include <stdio.h>

int main()
{
    0 && printf("1, not run!\n");
    1 && printf("2, must run!\n");
    0 || printf("3, must run!\n");
    1 || printf("4, not run!\n");

    return 0;
}
程序运行的输出如下:
ecy@ecy-geek:~/C++$ ./cond
2, must run!
3, must run!
    由此可知,&&和||都是快速与和快速或,上面"cond1 && cond2 || cond3"的执行有下面几种情况:
    一、cond1为假,那就不判断cond2了,接着判断cond3
    二、cond1为真,这又要分为两种情况:
    1、cond2为真,这就不需要判断cond3了
    2、cond2为假,那还得判断cond3
    根据这个分析,最上面的代码可以改写成一下形式:
int main()
{
    //第一个fork必须执行
    fork();

    //fork() && fork() || fork()
    //第一个fork也必须执行
    int ret1 = fork();

    //cond1 && cond2 || cond3
    //父进程返回值不为0,即cond1为真
    if(ret1 != 0)
    {
        int ret2 = fork();

        //cond2为假,必须判断cond3
        if(ret2 == 0)
        {
            fork();
        }
    }
    else //cond1为假时,必须判断cond3
    {
        fork();
    }

    //最后一个fork必须执行
    fork();

    sleep(100);

    return 0;
}
程序执行结果如下:
ecy@ecy-geek:~/C++$ ps
  PID TTY          TIME CMD
 1833 pts/0    00:00:00 bash
 2432 pts/0    00:00:00 fork
 2433 pts/0    00:00:00 fork
 2434 pts/0    00:00:00 fork
 2435 pts/0    00:00:00 fork
 2436 pts/0    00:00:00 fork
 2437 pts/0    00:00:00 fork
 2438 pts/0    00:00:00 fork
 2439 pts/0    00:00:00 fork
 2440 pts/0    00:00:00 fork
 2441 pts/0    00:00:00 fork
 2444 pts/0    00:00:00 fork
 2445 pts/0    00:00:00 fork
 2446 pts/0    00:00:00 fork
 2447 pts/0    00:00:00 fork
 2448 pts/0    00:00:00 fork
 2449 pts/0    00:00:00 fork
 2450 pts/0    00:00:00 fork
 2451 pts/0    00:00:00 fork
 2452 pts/0    00:00:00 fork
 2453 pts/0    00:00:00 fork
 2454 pts/0    00:00:00 ps
       符合预期,改成这种形式的代码之后就可以方便地插入一些代码,比如通过getpid来获取一些进程的进程号,并打印出来,以分析程序的运行 ^_^

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有