电脑技术学习

使用 UNIX System V IPC 机制共享应用程序数据

dn001

  您现在应该已经熟悉传递给 shmget 的参数了:密钥、大小和标志。此示例中的共享内存大小是单个整数。清单 7 与前一个示例的不同之处在于它对 IPC 密钥使用了 IPC_PRIVATE。当使用了 IPC_PRIVATE 时,将保证创建一个唯一的 IPC ID,并且预期应用程序将自己分发该 ID。在此示例中,父进程和子进程都知道 shmid,因为它们分别是对方的副本。fork 系统调用创建当前进程的第二个副本,称为子进程,此进程几乎与父进程完全相同。两个进程的执行都在 fork 之后恢复。返回值将用于确定当前进程是父进程还是子进程。

  父进程和子进程看起来相似。首先,shmat 系统调用被用于获得指向共享内存段的指针。shmat 需要共享内存 ID、一个指针和某些标志。该指针用于请求特定的内存地址。通过传递 0,内核可以随心所欲地选择任何内存地址。标志大部分是特定于供应商的,不过 SHM_RDONLY 是一个公共标志,用于指示不写入的段。如清单 7 所示,shmat 的常见用法是让内核决定一切。

  shmat 返回一个指向共享内存段的指针,此示例出于调试目的而将其打印到了屏幕上。然后每个进程依次修改该共享内存段,并打印出值。最后,父进程使用 shmctl(2) 来删除共享内存段。清单 8 显示了此程序的输出。

  清单 8. 共享内存示例的输出

sunbox$ ./shared_memory
Child pointer ff390000
Child value=1
Parent pointer ff380000
Parent value=1
Parent value=42
Child value=42

  您可以从输出中看到相同内存空间的共享。起初,共享内存中的值为 1,这是由子进程设置并由父进程读取的。然后父进程将该值设置为 42,并由子进程读取。请注意,父进程和子进程拥有指向共享内存段的不同指针地址,尽管它们是在访问相同的物理内存。在使用物理地址时,这会导致某些数据结构出现问题,例如链表,因此当您在共享内存中构建复杂结构时,可以使用相对寻址。

  此示例依赖在一个进程向共享内存写入时,另一个进程暂停。在实际应用程序中,这是不切实际的,因此,如果您的应用程序可能潜在地拥有多个向相同内存位置执行写入的进程,可以考虑使用信号量来锁定该区域。

  结束语

  Unix 提供了若干种用于 IPC 的方法。SysV IPC 方法是消息队列、信号量和共享内存。消息队列允许一个应用程序提交消息,其他应用程序可以在以后获得该消息,甚至是在发送应用程序已结束之后。信号量确保多个应用程序可以锁定资源并避免争用条件。共享内存允许多个应用程序共享一个公共内存段,从而提供了一种传递和共享大量数据的快速方法。您还可以将这些方法结合起来使用。例如,您可以使用信号量来控制对共享内存段的访问。

  IPC 方法对应用程序开发人员非常有用,因为它们提供了应用程序之间的标准通信方法,并且是跨不同 UNIX 风格可移植的。当您下次发现自己需要锁定资源或在进程之间共享数据时,可以试验一下 SysV IPC 机制。

标签: