11

现在我在理解fork()系统调用的工作时遇到了问题。我编写了以下代码:

#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}

此代码的输出如下:

现在我不明白为什么输出是这样的?

之后,我只需在我的代码中添加一行,输出就完全不同了。我的代码如下:

int main()
{
    int a, b;
    b=fork();

当我运行代码时,输​​出如下 2389my name is manish

 the value of b = 0

现在我对fork()呼叫的工作完全感到困惑。

我的问题如下:

  1. 如何fork()运作?
  2. 通话后控制在哪里fork()
  3. 任何机构都可以解释为什么编写的代码输出有问题吗?
  4. 为什么b在不同地方发生的输出意味着在第一个代码中的输出b = 2260就在输出之前,b = 0而 的值b = 2389不就在 之前b = 0

请解释我在问题中编写的代码中 fork 的工作,以便我可以正确学习它。

4

4 回答 4

40

首先理解为什么使用 fork 这个词来命名这个函数可能会有所帮助。听说过“岔路口”吗?在分叉处,该过程必须拆分路径。

首先,有一个进程正常执行,直到您到达fork呼叫为止。当调用 fork 时,会创建一个新进程,除了 fork 函数的返回值之外,它几乎在所有方面都与原始进程相同。新创建的进程称为子进程,因此产生它的进程称为父进程。

由于您希望为 fork 的每个分支执行不同的任务,因此您必须能够将子进程与父进程区分开来。这就是返回值的fork来源:fork将子进程(新创建的进程)的进程id(pid)返回给父进程;它返回 0 给孩子。另外,如果执行fork出错,返回值为-1。

在您的代码中,您不区分子进程和父进程,因此两个进程都运行fork调用之后的整个代码。

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

如您所见,两个进程在 fork 之后具有相同的代码,因此重复输出。也许如果您希望父进程输出 Manish 而子进程输出 Anil,那么您可以执行以下操作:

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it's probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}

最后,必须做的最后一条评论是,在您的代码中,输出似乎首先由一个进程整体执行,然后由另一个进程整体执行。情况可能并非总是如此。例如,操作系统可能允许父进程执行“manish”输出,然后让该进程等待,并将 cpu 交给子进程,然后子进程执行“manish”。但是,子进程可以继续执行“anil”和“b”输出,完成子进程的执行,从而将执行返回给父进程。现在父母通过输出'anil'和'b'本身来完成它的执行。运行此程序的最终输出可能类似于:

我的名字是 manish // 由父母执行
我的名字是阿尼尔//孩子
b = 0 的值 // 孩子
我的名字是阿尼尔//父母
b = 2244 的值 // 父级
manish.yadav@ws40-man-lin:~$

看一下手册页fork。还要查看waitpid父进程对子进程的正确处理,以免创建僵尸。

编辑:为了回答您在评论中的问题,我将回答您如何简单地连续运行每个流程。

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}

当然,不是最好的代码,但这只是为了说明这一点。这里的主要想法是waitpid调用,它会导致父进程等到它刚刚fork编辑的子进程终止。子进程完成后,父进程在waitpid调用后继续,开始循环的另一个迭代for并分叉另一个(下一个)进程。这一直持续到所有子进程都已按顺序执行并且执行最终返回到父进程。

于 2011-06-02T06:37:15.167 回答
5
  1. Fork 创建当前进程的副本。
  2. fork()原件和副本都从调用点继续执行。
  3. 因为你的代码被执行了两次,你的 print 语句也被计算了两次。在复制进程中, 的值为b0。在原始进程中, 的值为b复制进程的进程ID。
  4. 一旦您的进程开始并发运行,它们将由您的操作系统独立调度,因此您无法保证它们何时实际运行。
于 2011-06-02T05:17:56.920 回答
3
  1. 分叉由操作系统实现。它基本上创建一个子进程并在fork().

  2. 父进程接收文件进程的进程id:b=fork();b有进程id。子进程的 pid 为零。

  3. (和 4)因为这两个过程都可以并行运行或时间切片,所以您的输出会有所不同。

你可能想看看这个:http ://en.wikipedia.org/wiki/Fork_(operating_system )

于 2011-06-02T05:18:57.663 回答
1

你最好从这个开始。

在这里你可以找到解释和代码示例。

于 2011-06-02T05:19:02.553 回答