#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int main(int argc, char **argv) {
FILE *file;
file = fopen(argv[1], "r");
char buf[600];
char *pos;
pid_t parent = fork();
if(parent == 0) {
while (fgets(buf, sizeof(buf), file)) {
pid_t child = fork();
if(child == 0) {
/* is there a function I can put here so that it waits
once the parent is exited to then run?*/
printf("%s\n", buf);
return(0);
}
}
return(0);
}
wait(NULL);
return(0);
}
此处的目标是同时打印文件行,并行。
例如:
给定一个文件
a
b
c
$ gcc -Wall above.c
$ ./a.out file
a
c
b
$ ./a.out file
b
c
a
正如流程在同一时间运行一样。如果有一个wait子句等待父进程退出然后开始运行子进程,我想我可以让它工作。如上面的评论所示。一旦父进程退出,那么所有进程都将从print语句开始。
答案 0 :(得分:0)
如果你有:
int i = 10;
while (i > 0)
{
pid_t child = fork();
if(child == 0) {
printf("i: %d\n", i--);
exit(0);
}
}
然后子进程正在并发。根据内核数量和操作系统调度程序的不同,它们甚至可以同时运行。但是,printf
是缓冲区,因此无法确定行在屏幕上显示的顺序,并且在程序的执行之间会有所不同。由于printf
被缓冲,您很可能看不到其他线条重叠。但是,如果您将write
直接用于stdout
,则输出可能会重叠。
然而,在你的场景中,孩子们死得太快,因为你正在阅读
从文件(可能需要一段时间才能返回),到下一个fork
执行时,
以前的孩子已经死了。但这并没有改变这个事实,如果
孩子们会跑得足够长,他们会同时跑步而且
屏幕上的行顺序无法确定。
修改强>
正如Barmar在评论中指出的那样,write
是原子的。我抬头看着我
手册页并在 BUGS 部分中说明了这一点:
man 2写
根据POSIX.1-2008 / SUSv4 Section XSI 2.9.7(&#34;与常规文件操作的线程交互&#34;):
当对常规文件或符号链接进行操作时,以下所有函数在POSIX.1-2008中指定的效果中应相互原子化:...
随后列出的API包括
write()
和writev(2)
。在线程中应该是原子的效果中(并且 cesses)是文件偏移的更新。 但是,在3.14之前的Linux上,情况并非如此:如果两个进程共享一个 打开文件描述(请参阅open(2)
)同时执行write()
(或writev(2)
),然后I / O操作不是原子的 尊重更新文件偏移量,结果是两个进程输出的数据块可能(错误地)重叠。 此问题已在Linux 3.14中修复。
Sever多年前,我在write
上同时发现了stdout
的这种行为
孩子们打印的东西,这就是为什么我用write
写的那些,这些线可能
重叠。
答案 1 :(得分:0)
我不确定为什么你有一个外循环。您可以重写如下。创建子进程后,它们可以按任何顺序运行。因此,您可能看起来是“订单”中的输出,但在另一次运行中您可能会看到不同的顺序。它取决于您的操作系统的进程调度,并且出于您的目的,它们都以“并行”方式运行。所以你真的不需要确保父进程死了。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Incorrect args\n");
exit(1);
}
char buf[1024];
FILE *file = fopen(argv[1], "r");
while (fgets(buf, sizeof buf, file)) {
pid_t child = fork();
if(child == 0) {
write(STDOUT_FILENO, buf, strlen(buf));
_exit(0);
}
}
/* Wait for all child processes. */
while (wait(NULL) != -1);
}