在linux编程中通过pipe道在进程之间发送链表结构的最好方法是什么?

我尝试发送来自同一父级的subprocess之间的链接列表。 Child1需要find列表中的第一个素数,然后将其删除,然后将其倍数发送给Child2。 Child2做同样的事情,它发送到Child3和ChildN做同样的,并发送到Child1。 然而,我试图发送地址数据而不是所有的数字,但这是一种正确的方式,因为我可能会强制我的subprocess进入另一个地址空间。 那么你认为最好的方式是什么或者其他方式而不是发送地址?

您还可以使用System V共享内存(查看shmat函数)或mmap来在进程之间共享内存。 Boost.Interprocess有一个围绕这些调用的C ++包装,这样你就可以直接在共享内存中创建一个链表而不需要复制。

我假设你正在尝试使用多处理实现Eratothenes筛。 除非我误解你所描述的内容,否则你的算法可以改进。 你所描述的是一个系统,其中一个数字列表被传递给一个子进程,该进程在把列表的其余部分交给下一个子进程之前检查所有的值。

我将把这个算法作为一个进程的流水线来实现

 Generator -> [Prime2] -> Prime3 -> Prime5 -> Prime7 -> ... PrimeP 

下一个Prime进程是由链上最后一个进程创建的。 所以当生成8时,它被Prime2过滤掉并丢弃。 当发送9时,它被传递给Prime2,Prime2将其传递给Prime3,将其丢弃。 10则下降了2,而11则通过整个链条,而且由于Prime7之后在链条上没有链接,它以11为参数推出了一个新的过程。 Prime2应该像生成一样快地消费价值。 Prime 2正在计算20时,Prime3正在计算19,依此类推。 (优化:Prime2在实现视图中基本上是不必要的)。

当进程PrimeP创建新的进程PrimeN时,父进程创建2个管道,一个用于写入新进程,另一个用于从新进程读取。 然后,每个非终端进程节点将总共具有4个管道:两个正在到达/来自后继节点,并且两个正在到达/来自前任节点。 每个节点的未使用的末端可以关闭,但这不是严格必要的。

这个算法很好,因为管道在读取之前阻塞,直到读取一个值。 数字可以通过管道作为二进制数据发送:

 read(parent, &value, sizeof(value)) 

从以前的过程中读取数据

 write(stdout, &value, sizeof(value)) 

将数据写入下一个链接。

当生成最后一个数字时,链可以通过几种方式暂停:

  1. PoisonPill(例如值0或其他无效的数字)被传递。 这与从管道读取块很好地工作。
  2. SIGTERM被发送到进程组中的所有进程。
  3. 一个SIGTERM像PoisonPill一样通过链条(可能效率不如2)。

如果发生器需要收集所有的值,那么当PoisonPill发送时,可以使用另一组管道将它们发送回链路; 第二个PoisonPill也可以用作某种控制。

这有一些问题:

  1. 很多的行动是由前几个素数处理的。
  2. 有很多等待。
  3. 系统可以处理的实际进程的数量有一个上限。 如果你使用Haskell这样的东西,这不是一个问题,但它是C.
  4. 有很多管道正在使用。 第二套价值回报管可以是shmem,也可以是共享的fifo等。
  5. 大多数机器具有少量的处理器…只有少数几个可以同时运行。 解决这个问题的一个方法是限制线程的数量,但是每个进程都要管理好几个数字。 在这种情况下,您需要一次向每个PrimeProcessor发送一个数字块数组。 处理器将所有非主值删除,并将剩余的列表(数组)返回给父项。 父母然后将这些素数分配给PrimeProcessor(返回的值不保证在此处为素数;可能需要进一步分析),并发送新的一批整数。

要回答你的问题,发送一个链表没有任何意义,据我所知。 你要把它们一个接一个送到链条上,或者至少把它们当作一个数组。

将索引发送到列表而不是指针,或者将列表压缩到数组中,然后发送。

(听起来像是在实施Eratothenes的Sieve,无论如何它在数组上工作得更快。)

如果您正在使用管道,则通过不将该条目写入管道来“删除”条目。 所以,不要担心从列表中删除数据,只需考虑是否将从输入管道读取的条目写入输出管道。