在c语言中使用fork

时间:2011-06-02 05:05:39

标签: c fork systems-programming

现在我在理解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();

当我运行代码时输出如下  2389我的名字是manish

 the value of b = 0

现在我对fork()电话的工作感到困惑。

我的问题如下:

  1. fork()如何运作?
  2. 控件在fork()通话后的位置?
  3. 任何机构都可以解释为什么编写的代码输出有问题吗?
  4. 为什么b的输出发生在不同的地方意味着在第一个代码中 b = 2260的输出就在输出b = 0之前,而b = 2389的值不在b = 0之前?
  5. 请在问题中编写的代码中解释fork的工作原理,以便我能够正确学习它。

4 个答案:

答案 0 :(得分:39)

首先要理解为什么使用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'本身来完成它的执行。运行此程序的最终输出可能类似于:

my name is manish     // executed by parent
my name is anil       // child
the value of b = 0    // child
my name is anil       // parent
the value of b = 2244 // parent
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来终止。在子prcoess完成之后,父进程在waitpid调用之后继续,开始for循环的另一次迭代并分叉另一个(下一个)进程。这将继续,直到所有子进程按顺序执行,执行最终返回到父进程。

答案 1 :(得分:5)

  1. Fork会创建当前流程的副本。
  2. 原始副本和副本都从fork()被调用的位置继续执行。
  3. 因为您的代码执行了两次,所以您的print语句也会被评估两次。在复制的过程中,b的值为0.在原始过程中,b的值是复制过程的进程ID。
  4. 一旦您的进程同时开始运行,它们将由您的操作系统独立安排,因此您无法保证它们何时实际运行。

答案 2 :(得分:3)

  1. 分叉由操作系统实现。它基本上创建了一个子进程,并在fork()

  2. 之后开始运行它
  3. 父进程接收文件进程的进程ID:b=fork(); b具有进程ID。子进程的pid为零。

  4. (和4)因为这两个过程既可以并行运行,也可以按时间切片,因此输出会有所不同。

  5. 您可能需要查看此内容:http://en.wikipedia.org/wiki/Fork_(operating_system

答案 3 :(得分:1)

你最好从this开始。

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