【例5-26】 在进程用户空间映射一个共享匿名虚存区实现共享内存。
其执行结果如下。
父子进程的result 返回值指向共享的虚存区, 从映射函数mmap 的参数可以看到设置了MAP_ SHARED, 而sum 是双方都各有副本的, 所以不同进程中内容不同。 程序执行后父子进程都会睡眠20 秒, 到proc 的相应pid 目录下观察maps 文件, 可以看到新建的匿名虚存区。
【例5-27】 两个非亲缘进程利用文件映射共享内存实现通信。
(www.daowen.com)
其执行结果如下。
两个进程打开文件后, 没有利用文件读写函数操作文件在内存中的数据, 而是利用映射的方式, 通过映射的内存地址直接访问内存区域进行读写。 写文件的一方在执行中有10秒的睡眠, 此时我们如果执行读文件的程序, 该程序依然可以执行不会阻塞, 只是由于数据还未写入内存, 它读到的是空。 间隔几秒再执行, 就发现已经能从内存取到数据了。 不同于管道的是, 该过程没有为写入和读出方提供同步处理。
上述两个实例体现了进程可以直接通过内存映射操作内存, 基于内存管理的地址映射, 两个进程可通过各自得到的地址操作共享的同一块第三方缓冲区, 如图5.23 所示。 进程1 和进程2 可能是有亲缘关系到进程利用映射函数临时在内存中映射出一块内存缓冲, 也可以是非亲缘的进程, 利用文件映射得到一块第三方缓冲空间。 两进程映射得到的地址都是自己内存中的地址, 可能是不一样的, 但通过各自的内存映射表会指向同一块物理内存。
图5.23 两进程通过映射内存共享缓冲区示意图
消息队列和信号量、 管道等对象, 经由它们的数据需要在内核和用户空间进行额外的数据拷贝; 而共享内存和访问它的所有进程都处于用户空间, 进程通过地址映射的方式直接读写内存, 从而获得非常高的通信效率。 仍要注意的是, 由于被映射的物理内存被多个进程共享, 共享内存还需要搭配某种同步机制(如信号量)才能保证对共享存储区的读写操作不会出错乱。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。