2012-09-19 51 views
2

环境:在与海湾合作委员会x86_64的 2.6.32的Linux(RHEL 6.3)4.4.6新管道()和调用fork()C++ -

背景:我正在做一些繁重的数据捣鼓:约500 GB输入数据分布在〜2000个文件中。我的主要过程分叉N个孩子,每个孩子都会收到一份要紧缩的文件名列表。

我想要是用于控制台I/O通过父母。我一直在寻找到pipe(),看看如何使用poll(),直到有错误消息读给有我的父母块一些有趣的东西。看起来我需要N管(每个孩子一个)并且通过我想听的信号通过poll()。另外,我觉得,一旦我dup2(pipe[1], STDOUT)在每个孩子,每个孩子应该能写到管道与cout << stuff;像往常一样,对不对?

第一个,就是我上面说的关于多个管道,poll() ing和dup2()正确吗?

第二个,我该如何设置父poll()循环,让我一旦所有的孩子都死了,我就继续前进?

眼下,这个代码(不完整)的部分内容如下:

int status; 
while (1) { // wait for stuff 
    while ((status = poll(pollfds, ss.max_forks, -1)) > 1) 
     cout << "fork "<< status << ": " << pipes[status][0]; 
    if (status == -1) Die(errno, "poll error"); 
    if (status == 0) { // check that we still have at least one open fd 
     bool still_running = false; 
     for (int i=0; i<ss.max_forks; i++) { 
      // check pipe i and set still_running if it is not zero 
     } 
     if (!still_running) 
      break; 
    } 
} 

,我应该怎么设置我的时候应该的fcntl设置()?我想做O_ASYNC吗?我想做阻挡或非阻挡吗?

+0

你期望有多少个孩子?也许你最好使用单一的fifo或域套接字。 –

回答

2

其实,你需要关闭()在这两个进程(父母和子女)各自的“未使用”的一面,以确保“断管”遇到。因此,如果子进程写入Pipe [0],则父进程将从Pipe [1]中读取并关闭自己的Pipe [0]。同样,小孩会关闭Pipe [1]。

如果你这样做,当它从管道读的孩子已经死亡后,家长会得到一个错误。不要忘记使用一个waitpid()风格的函数来清理死亡进程。

您可能希望把手SETT为非阻塞,所以你可以读任何有无需使用1字节读取这是很没效率。虽然我只是用适当的缓冲区大小(通常为1024或4096)进行一次read()调用,但如果有更多的数据,就让下一个轮询触发。但是,我通常只有一个孩子可以工作,而不是几百个:-)

至于你的循环,你必须跟踪每个孩子的状态,并退出时,你还没有活着的孩子。

编辑:实际上,我发现我假设孩子是死的,当我得到即使POLLIN设置,或者读一个0字节,当我得到POLLERR或POLLHUP标志。不知道这种情况下是正确的......

+0

'read(2)'函数将返回0.它不完全是错误条件,它是file_的_end。 – fork0

+0

是的,我正在考虑补充说,作为一种“感觉”,因为这就是我正在寻找类似的设置使用select()。除了select()没有“HUP”,这也是一个强大的候选人:-) –

1

这里有一个问题,关于select() VS poll()What are the differences between poll and select?

但是,你有没有想过使用线程,而不是单独的进程?您可以更好地控制与线程的交互,通信通过数据结构而不是流水线I/O流。管道是昂贵的;你正在经历操作系统,你必须格式化输出的结果/解析输入的结果,也很昂贵。最后一点:无论您是使用轻量级线程还是重量级的fork/exec,除非拥有2000个CPU多处理器,否则不需要一次启动2000个。如果您争用CPU的线程/进程比拥有CPU的线程/进程更多,您将创建一个非常昂贵且持续的上下文交换的情况。