加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

Linux下的进程间通信:共享存储

发布时间:2019-05-10 16:30:02 所属栏目:Windows 来源:Marty Kalin
导读:学习在 Linux 中进程是如何与其他进程进行同步的。 本篇是 Linux 下进程间通信(IPC)系列的第一篇文章。这个系列将使用 C 语言代码示例来阐明以下 IPC 机制: 共享文件 共享内存(使用信号量) 管道(命名的或非命名的管道) 消息队列 套接字 信号 在聚焦

memwritermemreader 程序中,共享内存的主要着重点都在 shm_openmmap 函数上:在成功时,第一个调用返回一个备份文件的文件描述符,而第二个调用则使用这个文件描述符从共享内存段中获取一个指针。它们对 shm_open 的调用都很相似,除了 memwriter 程序创建共享内存,而 `memreader 只获取这个已经创建的内存:

  1. int fd = shm_open(BackingFile, O_RDWR | O_CREAT, AccessPerms); /* memwriter */
  2. int fd = shm_open(BackingFile, O_RDWR, AccessPerms); /* memreader */

有了文件描述符,接着对 mmap 的调用就是类似的了:

  1. caddr_t memptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

mmap 的第一个参数为 NULL,这意味着让系统自己决定在虚拟内存地址的哪个地方分配内存,当然也可以指定一个地址(但很有技巧性)。MAP_SHARED 标志着被分配的内存在进程中是共享的,最后一个参数(在这个例子中为 0 ) 意味着共享内存的偏移量应该为第一个字节。size 参数特别指定了将要分配的字节数目(在这个例子中是 512);另外的保护参数(AccessPerms)暗示着共享内存是可读可写的。

memwriter 程序执行成功后,系统将创建并维护备份文件,在我的系统中,该文件为 /dev/shm/shMemEx,其中的 shMemEx 是我为共享存储命名的(在头文件 shmem.h 中给定)。在当前版本的 memwritermemreader 程序中,下面的语句

  1. shm_unlink(BackingFile); /* removes backing file */

将会移除备份文件。假如没有 unlink 这个语句,则备份文件在程序终止后仍然持久地保存着。

memreadermemwriter 一样,在调用 sem_open 函数时,通过信号量的名字来获取信号量。但 memreader 随后将进入等待状态,直到 memwriter 将初始值为 0 的信号量的值增加。

  1. if (!sem_wait(semptr)) { /* wait until semaphore != 0 */

一旦等待结束,memreader 将从共享内存中读取 ASCII 数据,然后做些清理工作并终止。

共享内存 API 包括显式地同步共享内存段和备份文件。在这次的示例中,这些操作都被省略了,以免文章显得杂乱,好让我们专注于内存共享和信号量的代码。

即便在信号量代码被移除的情况下,memwritermemreader 程序很大几率也能够正常执行而不会引入竞争条件:memwriter 创建了共享内存段,然后立即向它写入;memreader 不能访问共享内存,直到共享内存段被创建好。然而,当一个写操作处于混合状态时,最佳实践需要共享内存被同步。信号量 API 足够重要,值得在代码示例中着重强调。

总结

上面共享文件和共享内存的例子展示了进程是怎样通过共享存储来进行通信的,前者通过文件而后者通过内存块。这两种方法的 API 相对来说都很直接。这两种方法有什么共同的缺点吗?现代的应用经常需要处理流数据,而且是非常大规模的数据流。共享文件或者共享内存的方法都不能很好地处理大规模的流数据。按照类型使用管道会更加合适一些。所以这个系列的第二部分将会介绍管道和消息队列,同样的,我们将使用 C 语言写的代码示例来辅助讲解。


(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读