Linux内核如何在不同进程之间实现共享内存机制?
进一步详细说明,每个流程都有自己的地址空间。例如,与进程B中的地址0x1000相比,进程A中的地址0x1000是不同的位置。
那么内核如何确保在具有不同地址空间的不同进程之间共享一块内存?
提前致谢。
答案 0 :(得分:4)
看看Beej's definitive guide to IPC on Linux。
包含示例代码和详细解释:
以及关于Linux上几乎所有关于IPC的所有内容的参考资料。
答案 1 :(得分:3)
进程间通信机制
进程相互通信并与内核通信以协调其活动。 Linux支持许多进程间通信(IPC)机制。信号和管道是其中两个,但Linux也支持以它们首次出现的Unix TM版本命名的System V IPC机制。
<强>信号强>
信号是Unix TM系统使用的最古老的进程间通信方法之一。它们用于向一个或多个进程发送异步事件。可以通过键盘中断或错误条件(例如,尝试访问其虚拟存储器中不存在的位置的过程)生成信号。 shell还使用信号向其子进程发送作业控制命令。 内核可以生成一组定义的信号,或者可以由系统中的其他进程生成,只要它们具有正确的权限即可。您可以使用kill命令(kill -l)列出系统的信号集。
<强>管道强>
常见的Linux shell都允许重定向。例如
$ ls | pr | LPR
将ls命令的输出通过管道列出目录的文件到pr命令的标准输入中,该命令对它们进行分页。最后,pr命令的标准输出通过管道传输到lpr命令的标准输入,该命令在默认打印机上打印结果。管道然后是单向字节流,它将来自一个进程的标准输出连接到另一个进程的标准输入。这两个进程都没有意识到这种重定向,并且行为与正常情况一样。它是在进程之间设置这些临时管道的shell。
在Linux中,管道使用两个文件数据结构实现,这两个文件数据结构都指向同一个临时VFS inode,它本身指向内存中的物理页面。图表显示每个文件数据结构包含指向不同文件操作例程向量的指针;一个用于写入管道,另一个用于从管道读取。
<强>套接字强>
假设您有许多协作进程从单个数据文件中读取记录并将记录写入单个数据文件。您希望严格协调该文件访问。您可以使用初始值为1的信号量,并在文件操作代码周围放置两个信号量操作,第一个用于测试和递减信号量值,第二个用于测试和递增它。访问该文件的第一个进程将尝试减少信号量的值并且它将成功,信号量的值现在为0.此过程现在可以继续使用数据文件但是如果另一个进程希望现在使用它试图减少信号量的值,它会失败,因为结果为-1。该过程将暂停,直到第一个进程完成数据文件。当第一个进程完成数据文件时,它将增加信号量的值,使其再次为1。现在等待进程可以被唤醒,这次它增加信号量的尝试将成功。
引自tldp.org。
答案 2 :(得分:0)
Linux中有两种共享内存。
如果A和B分别是父进程和子进程,则它们各自使用自己的pte访问共享内存。共享内存由fork机制共享。所以一切都很好,对吗?(更多详细信息,请查看内核函数copy_one_pte()和相关函数。)
如果A和B不是父级和子级,则它们使用公共密钥来访问共享内存。
让我们假设A通过System V shmget()用一个密钥创建了一个共享内存,并且相应地,内核在shmem / tmpfs中为进程A创建了一个文件(文件名是“ SYSTEMV + key”)。内部基于RAM的文件系统。它由kenrel挂载(检查shmem_init())。共享内存区域由shmem / tmpfs处理。基本上,当进程A访问共享内存区域时,它由页面错误机制处理。 如果进程B要访问由进程A创建的共享内存区域。进程B应该将shmget()与进程A使用的密钥相同。然后,进程B可以找到文件(“ SYSTEMV + key”)并将其映射到进程B的地址空间。