使用fork使进程同时运行

时间:2018-03-22 20:37:05

标签: c linux fork

#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语句开始。

2 个答案:

答案 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);
}