可以确定fork()的执行顺序吗?

时间:2011-07-14 16:47:58

标签: c fork scheduling

我正在练习教科书“操作系统概念第7版”,我对fork()的工作方式感到有些困惑。根据我的理解,fork()创建了一个与其父级同时运行的子进程。但是,我们如何确切知道哪个进程首先运行?我的意思是执行的顺序。

  

问题
  使用fork()系统调用编写C程序,在子进程中生成Fibonacci序列。序列号将在命令行中提供。

这是我的解决方案:

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

void display_fibonacci_sequence( int n ) {
    int i = 0;
    int a = 1;
    int b = 1;
    int value;
    printf( "%d, %d, ", a, b );
    for( ;i < n - 2; ++i ) {
        value = a + b;
        printf( "%d, ", value );
        a = b;
        b = value;
    }
    printf( "\n" );
}

int main( int argc, char** argv ) {
    int n;
    pid_t pid;
    pid = fork();
    if( argc != 2 ) {
        fprintf( stderr, "Invalid arguments" );
        exit( -1 );
    }
    n = atoi( argv[1] );

    if( pid < 0 ) {
        fprintf( stderr, "Fork failed" );
        exit( -1 );
    }
    else if( pid == 0 ) {
        display_fibonacci_sequence( n );
    }
    else { // parent process
        // what do we need to do here? 
    }
}

说实话,我认为使用fork和不使用fork之间没有任何区别。此外,如果我希望进程处理来自用户的输入,并让进程处理显示,我该怎么办呢?

5 个答案:

答案 0 :(得分:14)

你问很多问题,我会尝试以方便的顺序回答它们。

第一个问题

  

说实话,我觉得使用fork之间没有任何区别   使用fork。

那是因为这个例子不是很好。在您的示例中,父级不执行任何操作,因此fork无用。

第二

else {
    // what do we need to do here? 
}

您需要wait(2)才能让孩子终止。请务必仔细阅读该页面。

第三

  

我希望父进程处理来自用户的输入,然后让   子进程处理显示

在fork之前读取输入并“处理”if (pid == 0)

中的显示

  

但是,我们如何确切知道哪个流程首先运行?

很少有节目应该关注这一点。你无法知道执行的顺序,它完全取决于环境。 TLPI说:

  

在fork()之后,它是不确定的进程 - 父进程还是   child-next可以访问CPU。在多处理器系统上,它们可以同时访问CPU。

     

隐式或明确依赖于特定的应用程序   执行顺序是为了实现正确的结果打开   因竞争条件而失败

也就是说,操作系统可以让您控制此订单。例如,Linux有/proc/sys/kernel/sched_child_runs_first

答案 1 :(得分:9)

我们不知道哪个先行,父母或孩子。这就是为什么父母通常必须等待子进程完成,如果它们之间的执行顺序有一些依赖。

在您的具体问题中,没有任何特殊原因可以使用fork()。你的教授可能只是为了一个简单的例子而给你这个。

如果您希望父级处理输入并计算要计算的子级,您只需将调用移动到处理命令行参数点之下的fork()。使用与上述相同的基本逻辑,让孩子调用display_fibonacci_sequence,让父母等待

答案 2 :(得分:2)

选择运行system scheduler选择的进程,与操作系统上运行的任何其他应用程序不同。生成的进程被视为调度程序在队列中分配优先级或点或任何实现的任何其他进程。

答案 3 :(得分:2)

虽然您无法控制在fork之后首先安排哪个进程(父进程或子进程)(实际上在SMP /多核上它可能两者都!)但有许多方法可以同步这两个过程,在执行任何重要操作之前,让一个等待直到另一个到达某一点。一种经典,极易携带的方法如下:

  1. fork之前,请致电pipe以创建管道。
  2. fork之后,想要等待的进程应立即关闭管道的写入端并在管道的读取端调用read
  3. 另一个进程应立即关闭管道的读取端,并等待关闭管道的写入端,直到它准备好让其他进程运行。 (read将在另一个过程中返回0)

答案 4 :(得分:1)

  

但是,我们如何确切知道哪个进程首先运行?我的意思是   执行顺序。

无法保证首先运行哪一个。 fork如果是孩子,则返回0,如果是父,则返回孩子的pid。从理论上讲,它们可以在多处理器系统上完全同时运行。如果您确实想确定哪个先运行,则可以在两个进程之间建立共享锁。首先获得锁定的人可以说先跑了。

关于在你的其他声明中做什么。您需要等待子进程使用waitwaitpid退出。

  

说实话,我认为使用fork与不使用fork之间没有任何区别。

不同之处在于您创建了子进程。系统进行计算的另一个过程。对于这个简单的问题,最终用户体验是相同的。但是当你编写像需要同时处理事物的服务器这样的系统时,fork会有很大不同。

  

此外,如果我希望父进程处理来自用户的输入,并让子进程处理显示,我该怎么办呢?

您似乎已经安装了该设置。父进程只需要等待子进程完成。子进程将printf结果发送给终端。父进程当前从命令行获取用户输入。