在Linux上跨进程共享数据

4
在我的应用程序中,有一个进程分叉出一个子进程child1,这个子进程将一个巨大的二进制文件写入磁盘并退出。然后父进程分叉出另一个子进程child2,它读取这个巨大的文件以进行进一步处理。
文件的转储和重新加载使我的应用程序变得很慢,我正在考虑可能避免完全进行磁盘I/O的方法。我已经确定的可能的方法是ram-disk或tmpfs。我是否可以在我的应用程序中实现ram-disk或tmpfs?或者是否有其他方法可以完全避免磁盘I/O并可靠地在进程间发送数据。

为了更好地说明问题,父进程实际上会分叉出3-4个子进程,这些子进程会将数据写入磁盘,然后由后续的子进程读取这些文件。所有这些子进程不会同时存在,并在将数据写入磁盘后退出。 - user900563
由于涉及到许多进程,我认为设置管道可能会变得过于复杂和脆弱。相反,如果我可以构建一个封装的API来模拟我需要的一些东西,那就太棒了! - user900563
1
为什么要分叉?使用线程并将文件保留在内存中。 - hookenz
7个回答

5
在分叉之前创建一个匿名共享内存区域,然后所有子进程都可以在分叉之后使用它:
char *shared = mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

请注意,当共享内存时,您需要一些同步机制。一种实现方式是在共享内存区域中放置一个互斥锁或信号量。


3
如果两个子进程不同时运行,管道或套接字将无法为您工作 - 它们的缓冲区对于“巨大的二进制文件”太小了,第一个进程将阻塞等待读取数据的任何内容。
在这种情况下,您需要一些共享内存。您可以使用SysV IPC共享内存API、POSIX共享内存API(最近Linux内部使用tmpfs)或直接使用tmpfs上的文件(通常挂载在/dev/shm上,有时在/tmp上)文件系统。

是的,子进程不会同时运行,但父进程会一直处于活动状态,直到最后一个子进程退出。我一直在考虑直接使用tmpfs文件系统上的文件,但不知道如何从程序内部实现。有什么建议吗? - user900563

2
一个命名管道正是你想要的。你可以像操作文件一样往里面写入数据和读取数据,但不需要将其存储在磁盘上。

为什么要使用命名管道,当进程是从单个进程派生而来并可以直接共享文件描述符? - Jacek Konieczny

2

您可以使用管道、套接字并利用Linux内核的sendfile()splice()功能(它们可以避免数据复制)。


1

您可以使用管道在进程之间传递数据。这里有一个很好的概述和示例实现。


0

就像您的情况一样,第一个子进程child1在child2出现之前退出,因此套接字通信或未命名管道将无法帮助解决问题,

但是共享内存可以解决这个问题: 在child1中创建一个具有所有读取权限的共享内存段,并在其中执行文件转储任务, 在child2中将共享内存段附加到当前进程空间并读取已转储的数据。


欢迎来到SO。请解释如何解决问题并给出一些示例。您可以阅读此内容:http://stackoverflow.com/help/how-to-answer - Sebi

0
生成两个进程并通过套接字传输数据。TCP是最容易入手的,但如果您想要更高的效率,请使用Unix域套接字。这假定您不关心数据本身被写入磁盘。

实际上,这2个子进程不会同时存在。第一个完成工作,转储文件并退出,之后另一个子进程被fork,它会加载这个文件并完成剩下的处理。我能否在父进程和子进程1之间建立一个套接字,然后再建立父进程和子进程2之间的套接字? - user900563
让它们同时运行怎么样?这可能会极大地减少总运行时间,作为一个附带的好处。 - John Zwinck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接