| memwriter和memreader程序中,共享内存的主要着重点都在shm_open和mmap函数上:在成功时,第一个调用返回一个备份文件的文件描述符,而第二个调用则使用这个文件描述符从共享内存段中获取一个指针。它们对shm_open的调用都很相似,除了memwriter程序创建共享内存,而 `memreader 只获取这个已经创建的内存:
 int fd = shm_open(BackingFile, O_RDWR | O_CREAT, AccessPerms); /* memwriter */int fd = shm_open(BackingFile, O_RDWR, AccessPerms); /* memreader */
 有了文件描述符,接着对 mmap的调用就是类似的了: 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中给定)。在当前版本的memwriter和memreader程序中,下面的语句 shm_unlink(BackingFile); /* removes backing file */
 将会移除备份文件。假如没有 unlink这个语句,则备份文件在程序终止后仍然持久地保存着。 memreader和memwriter一样,在调用sem_open函数时,通过信号量的名字来获取信号量。但memreader随后将进入等待状态,直到memwriter将初始值为 0 的信号量的值增加。
 if (!sem_wait(semptr)) { /* wait until semaphore != 0 */
 一旦等待结束,memreader将从共享内存中读取 ASCII 数据,然后做些清理工作并终止。 共享内存 API 包括显式地同步共享内存段和备份文件。在这次的示例中,这些操作都被省略了,以免文章显得杂乱,好让我们专注于内存共享和信号量的代码。 即便在信号量代码被移除的情况下,memwriter和memreader程序很大几率也能够正常执行而不会引入竞争条件:memwriter创建了共享内存段,然后立即向它写入;memreader不能访问共享内存,直到共享内存段被创建好。然而,当一个写操作处于混合状态时,最佳实践需要共享内存被同步。信号量 API 足够重要,值得在代码示例中着重强调。 总结上面共享文件和共享内存的例子展示了进程是怎样通过共享存储来进行通信的,前者通过文件而后者通过内存块。这两种方法的 API   相对来说都很直接。这两种方法有什么共同的缺点吗?现代的应用经常需要处理流数据,而且是非常大规模的数据流。共享文件或者共享内存的方法都不能很好地处理大规模的流数据。按照类型使用管道会更加合适一些。所以这个系列的第二部分将会介绍管道和消息队列,同样的,我们将使用  C 语言写的代码示例来辅助讲解。 
 (编辑:源码网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |