Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c中的fork()系统调用 #包括 #包括 int main() { fork(); fork()&&fork()| fork(); fork(); printf(“分叉的”); 返回0; }_C_Unix_Fork - Fatal编程技术网

c中的fork()系统调用 #包括 #包括 int main() { fork(); fork()&&fork()| fork(); fork(); printf(“分叉的”); 返回0; }

c中的fork()系统调用 #包括 #包括 int main() { fork(); fork()&&fork()| fork(); fork(); printf(“分叉的”); 返回0; },c,unix,fork,C,Unix,Fork,这会导致理解如何计算执行程序后生成的进程数的困难? 帮我弄清楚 平台——UBUNTU 10.04您不应该像这样使用fork()。从未。然而,在现实生活中你不需要这样做。 如何使用它: #include <stdio.h> #include <unistd.h> int main() { fork(); fork() && fork() || fork(); fork();

这会导致理解如何计算执行程序后生成的进程数的困难? 帮我弄清楚

平台——UBUNTU 10.04

您不应该像这样使用fork()。从未。然而,在现实生活中你不需要这样做。 如何使用它:

    #include <stdio.h>
    #include <unistd.h>
    int main()
    {
       fork();
       fork() && fork() || fork();
       fork();

     printf("forked\n");
     return 0;
    }
intmain(){
/*代码*/
pid_t pid=fork();
if(pid<0){
/*错误,未生成子进程*/
}
如果(pid>0){
/*我们是父进程,pid是生成的一个子进程的进程ID*/
}
/*否则,我们就是子进程,在父进程中调用fork()之后只运行一个命令*/
/*还有代码吗*/
返回0;
}

将文件保存为
fork count.c
。然后用gcc fork count.c-o fork count编译它。然后可以运行它并使用
/fork count | wc-l
计算输出行数

int main() {
    /* code */
    pid_t pid = fork();
    if (pid < 0) {
        /* error, no child process spawned */
    }
    if (pid > 0) {
        /* we are the parent process, pid is the process ID of the ONE child process spawned */
    }
    /* else, we are the child process, running exactly one command later the fork() was called in the parent. */
    /* some more code */
    return 0;
}
fork
系统调用返回一个整数:父进程中进程的PID和子进程中的0。如果发生错误,则不创建任何进程,并返回-1

|
&&
是逻辑运算符

如果在计算左操作数后知道运算符的结果,则要求运算符短路(即不计算右操作数):

  • 对于
    |
    运算符,如果其左操作数为!=0
  • 对于
    &&
    运算符,如果其左操作数为==0,则不计算其右操作数

让我们按照叉树进行操作,假设没有一个叉出现故障

fork()

现在我们有两个过程,到目前为止,谁是孩子,谁是父母都不重要,称它们为p1和p2

fork()

这两个进程都会产生另一个子进程,因此我们有4个进程,其中两个进程(p3,p4)的结果为零,另外两个进程(p1和p2)的结果为非零

p1和p2再次分叉,给出p5和p6,总共六个进程。在p1和p2中,
&&
的计算结果为true,因此它们不会在此行中再次分叉。对于p3、p4、p5、p6,
和&
的计算结果为false,因此它们会分叉

在这里,生成四个新进程,总共得到6+4=10

fork()


10个过程中的每一个都再次分叉,得到20个。

我找到了这个问题的正确解释:

fork()系统调用将进程作为正在增长的二叉树的叶子生成。如果我们调用fork()两次,它将生成22=4个进程。这4个过程构成了二叉树的叶子树。一般来说,如果我们是级别l,并且fork()被无条件调用,那么级别(l+1)将有2l个进程。它相当于二叉树中(l+1)级的最大子节点数

作为另一个例子,假设我们已经无条件地调用了fork()调用3次。我们可以使用三个级别的完整二叉树来表示生成的进程。在第3级,我们将有23=8个子节点,对应于运行的进程数

关于C/C++逻辑运算符的说明:

逻辑运算符&&的优先级高于| |,并且具有从左到右的关联性。执行左操作数后,将估计最终结果,右操作数的执行取决于左操作数的结果以及操作类型

在AND(&&)的情况下,对左操作数求值后,仅当左操作数求值为非零时,才会对右操作数求值。在OR(| |)的情况下,在计算左操作数后,仅当左操作数的计算结果为零时,才会计算右操作数

fork()的返回值:

fork()的手册页引用了以下关于返回值的摘录

成功时,在父进程中返回子进程的PID,在子进程中返回0。失败时,在父进程中返回-1,不创建子进程,并正确设置errno

PID类似于进程句柄,用无符号int表示。我们可以得出结论,fork()将在父级中返回非零,在子级中返回零。让我们分析一下程序。为了便于记法,请按如下所示标记每个fork()

              || fork();
#包括
int main()
{
fork();/*A*/
(fork()/*B*/&&
fork()/*C*/)| |/*B和C根据优先级分组*/
fork();/*D*/
fork();/*E*/
printf(“分叉的”);
返回0;
}
前两个fork()调用是无条件调用的

在0级,我们只有主进程。main(图中的m)将创建子C1,两者都将继续执行。孩子们按照他们创造的顺序被编号

在第1级,我们运行m和C1,并准备执行fork()–B(注意,B、C和D被命名为&&和| |运算符的操作数)。初始表达式B将在此级别运行的每个子进程和父进程中执行

在第2级,由于fork()–B由m和C1执行,我们将m和C1作为父级,将C2和C3作为子级

fork()–B的返回值在父级中不为零,在子级中为零。由于第一个运算符是&,由于返回值为零,子C2和C3将不会执行下一个表达式(fork()-C)。父进程m和C1将继续使用fork()–C。子进程C2和C3将直接执行fork()–D,以评估逻辑OR运算的值

在3级,我们将m、C1、C2、C3作为运行进程,将C4、C5作为子进程。表达式现在简化为((B&&C)| | D),此时(B&&C)的值是显而易见的。在父母中它是非零的,在孩子中它是零的。因此,知道总体B&C|D结果的父母将跳过fork()–D的执行。因为,在评估为z的儿童(B&C)中
   && fork()
              || fork();
     #include <stdio.h>
     int main()
      {
       fork(); /* A */
      (       fork()  /* B */ &&
      fork()  /* C */ ) || /* B and C are grouped according to precedence */
      fork(); /* D */
      fork(); /* E */

      printf("forked\n");
      return 0;
     }