美文网首页
2019-08-13

2019-08-13

作者: 起点_882d | 来源:发表于2019-08-13 11:45 被阅读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() 从2到4标号。

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

     if(fork2 返回> 0)

     {

     if(fork3 返回> 0)

     ; //1个进程

     else(fork3 返回== 0)

    fork4 //2个进程

     }

     else

    {

     fork4//2个进程

     }

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

    #include

    #include

    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

    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来获取一些进程的进程号,并打印出来,以分析程序的运行 ^_^

    相关文章

      网友评论

          本文标题:2019-08-13

          本文链接:https://www.haomeiwen.com/subject/feevjctx.html