我正在练习教科书“操作系统概念第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
之间没有任何区别。此外,如果我希望父进程处理来自用户的输入,并让子进程处理显示,我该怎么办呢?
答案 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 /多核上它可能两者都!)但有许多方法可以同步这两个过程,在执行任何重要操作之前,让一个等待直到另一个到达某一点。一种经典,极易携带的方法如下:
fork
之前,请致电pipe
以创建管道。fork
之后,想要等待的进程应立即关闭管道的写入端并在管道的读取端调用read
。read
将在另一个过程中返回0)答案 4 :(得分:1)
但是,我们如何确切知道哪个进程首先运行?我的意思是 执行顺序。
无法保证首先运行哪一个。 fork
如果是孩子,则返回0
,如果是父,则返回孩子的pid
。从理论上讲,它们可以在多处理器系统上完全同时运行。如果您确实想确定哪个先运行,则可以在两个进程之间建立共享锁。首先获得锁定的人可以说先跑了。
关于在你的其他声明中做什么。您需要等待子进程使用wait
或waitpid
退出。
说实话,我认为使用
fork
与不使用fork
之间没有任何区别。
不同之处在于您创建了子进程。系统进行计算的另一个过程。对于这个简单的问题,最终用户体验是相同的。但是当你编写像需要同时处理事物的服务器这样的系统时,fork
会有很大不同。
此外,如果我希望父进程处理来自用户的输入,并让子进程处理显示,我该怎么办呢?
您似乎已经安装了该设置。父进程只需要等待子进程完成。子进程将printf
结果发送给终端。父进程当前从命令行获取用户输入。