linux内核如何在两个进程之间实现共享内存

时间:2013-07-06 13:57:52

标签: linux-kernel operating-system shared-memory

Linux内核如何在不同进程之间实现共享内存机制?

进一步详细说明,每个流程都有自己的地址空间。例如,与进程B中的地址0x1000相比,进程A中的地址0x1000是不同的位置。

那么内核如何确保在具有不同地址空间的不同进程之间共享一块内存?

提前致谢。

3 个答案:

答案 0 :(得分:4)

看看Beej's definitive guide to IPC on Linux

包含示例代码详细解释

  1. fork()
  2. 信号
  3. Pipes
  4. FIFO
  5. 文件锁定
  6. 消息队列
  7. 信号灯
  8. 共享内存段
  9. 内存映射文件
  10. Unix套接字
  11. 以及关于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。

enter image description here

在Linux中,管道使用两个文件数据结构实现,这两个文件数据结构都指向同一个临时VFS inode,它本身指向内存中的物理页面。图表显示每个文件数据结构包含指向不同文件操作例程向量的指针;一个用于写入管道,另一个用于从管道读取。

<强>套接字

  • 消息队列:消息队列允许一个或多个进程写入消息,这些消息将由一个或多个读取进程读取。 Linux维护一个消息队列列表,即msgque向量;其中的每个元素都指向一个完全描述消息队列的msqid_ds数据结构。创建消息队列时,将从系统内存中分配新的msqid_ds数据结构并将其插入到向量中。 enter image description here
  • System V IPC机制:Linux支持三种类型的进程间通信机制,这些机制最初出现在Unix TM System V(1983)中。这些是消息队列,信号量和共享内存。这些System V IPC机制都共享通用的身份验证方法。进程只能通过系统调用将唯一引用标识符传递给内核来访问这些资源。使用访问权限检查对这些System V IPC对象的访问,就像检查对文件的访问一样。 System V IPC对象的访问权限由对象的创建者通过系统调用设置。每个机制使用对象的引用标识符作为资源表的索引。它不是一个直接的索引,但需要一些操作来生成索引。
  • 信号量:信号量最简单的形式是内存中的一个位置,其值可以由多个进程测试和设置。就每个过程而言,测试和设置操作是不间断的或原子的;一旦开始,没有什么能阻止它。测试和设置操作的结果是添加信号量的当前值和设置值,可以是正数或负数。根据测试结果和设置操作,一个过程可能必须休眠,直到另一个过程改变了semphore的值。信号量可用于实现关键区域,关键代码区域一次只能执行一个进程。

假设您有许多协作进程从单个数据文件中读取记录并将记录写入单个数据文件。您希望严格协调该文件访问。您可以使用初始值为1的信号量,并在文件操作代码周围放置两个信号量操作,第一个用于测试和递减信号量值,第二个用于测试和递增它。访问该文件的第一个进程将尝试减少信号量的值并且它将成功,信号量的值现在为0.此过程现在可以继续使用数据文件但是如果另一个进程希望现在使用它试图减少信号量的值,它会失败,因为结果为-1。该过程将暂停,直到第一个进程完成数据文件。当第一个进程完成数据文件时,它将增加信号量的值,使其再次为1。现在等待进程可以被唤醒,这次它增加信号量的尝试将成功。 enter image description here

  • 共享内存:共享内存允许一个或多个进程通过其所有虚拟地址空间中显示的内存进行通信。虚拟存储器的页面由每个共享过程中的页表条目引用&#39;页表。它不必在所有过程中处于相同的地址。虚拟内存。与所有System V IPC对象一样,通过密钥和访问权限检查来控制对共享内存区域的访问。共享内存后,不会检查进程如何使用它。它们必须依赖其他机制(例如System V信号量)来同步对内存的访问。 enter image description here

引自tldp.org

答案 2 :(得分:0)

Linux中有两种共享内存。

  1. 如果A和B分别是父进程和子进程,则它们各自使用自己的pte访问共享内存。共享内存由fork机制共享。所以一切都很好,对吗?(更多详细信息,请查看内核函数copy_one_pte()和相关函数。)

  2. 如果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的地址空间。