linux 编程问题:子进程1和2为啥也能对管道进行操作?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux 编程问题:子进程1和2为啥也能对管道进行操作?相关的知识,希望对你有一定的参考价值。
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/fcntl.h>
main()
const int msg_len = 30;
int pid1,pid2;
int fd[2];
pipe(fd); /*创建一个管道*/
pid1=fork();
if(pid1 == 0)
/*子进程1 */
//lockf(fd[1],1,0); //加锁
write(fd[1], "Message from child1!", msg_len); /*向管道写入消息 */
sleep(5);
//lockf(fd[1],0,0);; //解锁
else
pid2 = fork();
if(pid2 ==0)
/*子进程2 */
//lockf(fd[1],1,0); // 加锁
write(fd[1], "Message From child2!", msg_len); /*向管道写入消息 */
sleep(5);
//lockf(fd[1],0,0); // 解锁
else
/*父进程 */
char in_msg[100];
wait(0); /*同步*/
read(fd[0], in_msg, msg_len); /*从管道中读*/
printf("%s\n", in_msg);
wait(0);
read(fd[0], in_msg, msg_len); /*从管道中读*/
printf("%s\n", in_msg);
exit(0);
因为父进程用pipe()创建了一个无名管道,子进程1和2都知道该管道文件描述符,所以进程1和2都能对管道进行操作。本回答被提问者采纳
在Linux编程中通过管道在进程之间发送链表结构的最佳方法是啥
【中文标题】在Linux编程中通过管道在进程之间发送链表结构的最佳方法是啥【英文标题】:What is the best way to send linked list structure between processes via pipe in linux programming在Linux编程中通过管道在进程之间发送链表结构的最佳方法是什么 【发布时间】:2011-03-08 00:58:51 【问题描述】:我尝试在来自同一个父进程的子进程之间发送链表。 Child1 需要在列表中找到第一个质数并将其删除,然后将其倍数发送给 Child2。 Child2 做同样的事情并发送给 Child3,而 ChildN 做同样的事情并发送给 Child1。但是,我尝试在而不是所有数字之间发送地址数据,但这是一种正确的方式,因为也许我强迫我的子进程进入另一个地址空间。那么,除了发送地址之外,您认为最好的方式是什么或任何其他方式?
【问题讨论】:
【参考方案1】:您还可以使用 System V 共享内存(查看 shmat
等函数)或 mmap
在进程之间共享内存。 Boost.Interprocess 对这些调用有一个 C++ 包装器,这样您就可以直接在共享内存中创建一个链表,而无需复制。
【讨论】:
【参考方案2】:我假设您正在尝试使用多处理实现 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))
将数据写入下一个链接。
当生成最后一个数字时,可以通过多种方式停止链:
-
PoisonPill(例如值 0 或其他无效数字)被传递。这在从管道中读取时非常适用于块。
向进程组中的所有进程发送 SIGTERM。
SIGTERM 像 PoisonPill 一样沿链向下传递(可能不如 2 有效)。
如果生成器需要收集所有值,则可以在发送 PoisonPill 时使用另一组管道将它们发送回链;第二个 PoisonPill 也可以用作某种控制。
这有一些问题:
-
很多动作都由前几个素数处理。
有很多等待。
系统可以处理的实际进程数有上限。如果您使用的是 Haskell 之类的东西,这不是问题,但它适用于 C。
使用了很多管道。用于返回值的第二组管道可以是 shmem,也可以是共享的 fifo 等。
大多数机器的处理器数量很少...只有少数可以同时运行。解决此问题的一种方法是限制线程数,但让每个进程管理多个数字。在这种情况下,您可能希望一次向每个 PrimeProcessor 发送一个数字块数组。处理器将所有非质数清空,并将剩余的列表(数组)返回给父级。然后父进程将这些素数分配给 PrimeProcessor(此时不能保证返回的值是素数;可能需要做进一步的分析)并发送新一批整数。
据我所知,要回答您的问题,发送链接列表没有意义。您将把它们一个一个地发送到链中,或者至少作为一个数组发送。
【讨论】:
【参考方案3】:要么将索引而不是指针发送到列表中,要么将列表压缩到数组中并发送。
(听起来您正在实现 Eratothenes 筛,无论如何它在数组上运行得更快。)
【讨论】:
【参考方案4】:如果您使用管道,则通过不将该条目写入管道来“删除”条目。所以不用担心从列表中删除数据,只需考虑是否应该将从输入管道读取的条目写入输出管道。
【讨论】:
以上是关于linux 编程问题:子进程1和2为啥也能对管道进行操作?的主要内容,如果未能解决你的问题,请参考以下文章