c - 在终端上使用 fork 时,要打印的文本正在命令行上打印,而不是打印空间
问题描述
因此,在 ubuntu 终端中,当我使用 fork 运行一段简单的代码从子进程和父进程打印时,终端会在命令行上而不是在它之前打印子进程的打印语句。我想知道是否有办法解决它。
我对使用系统调用有点陌生,所以我真的没有尝试很多事情
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[]){
printf("(%d) Start\n", (int)getpid());
int rc = fork();
if(rc < 0 ){
fprintf(stderr, "Error\n");
exit(1);
}
else if(rc == 0){
printf("(%d) Hello from the child, I got %d. My parent is %d\n", (int)getpid(), (int)rc, (int)getppid());
}
else{
printf("(%d) Hello from the parent, I got %d. My parent is %d\n", (int)getpid(), (int)rc, (int)getppid());
}
return 0;
}
我希望打印的语句都在两个命令行之间,但最后一行一直打印在命令行上:
解决方案
这是竞态条件的经典示例。在fork
调用之后,根据定义,您拥有两个独立的进程和两个控制线程。从理论上讲,它们是并行运行的。(在多处理器或多核机器上,它们实际上可能并行运行。)
在父级中,我们发生了这些事情:
- 打印“来自父母的你好”
- 退出回调用者
- 来电者打印下一个提示
在孩子身上,我们发生了这些事情
- 打印“来自孩子的你好”
- 出口
它是调用 shell 的子进程的父进程(在此上下文中)。所以shell正在等待的是父进程;父进程的退出(第 2 步)将触发下一个 shell 提示符的打印(第 3 步)。说孩子退出后会发生什么会更复杂,但由于它不会导致打印任何内容(或我们可以看到的任何内容),所以它最终并不重要。
但是由于我们有两个控制线程和一个竞争条件,我们可以看到不同的结果,具体取决于各种打印步骤的交错方式:
thread of control #1 thread of control #2
------ -- ------- -- ------ -- ------- --
1. Hello from the parent
4. Hello from the child
3. next shell prompt
或者
1. Hello from the parent
3. next shell prompt
4. Hello from the child
或者可能
4. Hello from the child
1. Hello from the parent
3. next shell prompt
但是你得到的这些结果中的哪一个实际上取决于任何事情。(这是竞争条件的本质。)所以我对你教授的计算机表现出不同的行为并不感到惊讶。(一方面,虽然 MacOS 确实非常像 Unix,但它基于底层的Mach 微内核,这改变了一些东西。)
如果你仍然不满意,这里有一个——可能是牵强的——类比。
听起来您想在程序(整个程序)完成之前不应该返回另一个 shell 提示符。听起来您认为“程序”在完成后应该不可能打印任何内容,也就是说,在您看到下一个表明它已完成的 shell 提示符之后。
假设您经营一个治疗中心。假设您有一个“尖叫室”,人们可以在其中大声尖叫,以发泄他们的挫败感。所以当你听到那个房间里的尖叫声时,你就知道是你的一个病人发出的,但是如果那里没有病人,你就不会期望听到任何尖叫声。
所以有一天一个压力很大的女人进来了,你把她带到尖叫的房间里,你听到了相当多的尖叫声,但过了一会儿她又回来了,你把门上的小标志从“占用”回到“未占用”。但是,令你惊讶的是,你听到门后传来另一声尖叫(更像是哭声)......
哦,我有没有提到这个女人一开始压力很大的原因是她怀孕了,快要生了?
推荐阅读
- javascript - 将 css 样式应用于我的 Angular 应用程序中的所有启动对话框
- r - 如何以某种方式融化/转置我的数据?
- java - 如何区分在没有互联网连接的情况下引发的异常与没有可用服务器/或错误 url 的情况?
- python - cv2.matchTemplate 在图像中找到错误的模板
- list - 分而治之的乘法问题c ++
- docker - Docker CMD 在容器内的后台运行 bash 脚本
- asp.net - 如何为 DataGridView 创建自增列?
- c# - Visual Studio 中非常慢的编译程序执行时间与执行时间(附加调试器)
- c# - 如何确定单帧 DICOM 是否实际上是 MRI 切片?
- dspace - 更改语言时出现 DSpace 内部错误