共享内存才是实现进程间通信最简单也是最直接的方法
共享内存是进程间通信中最简单的方式之一 。共享内存允许两个或更多进程访问同一块内存 , 就如同malloc()函数向不同进程返回了指向同一个物理内存区域的指针 。当一个进程改变了这块地址中的内容的时候 , 其它进程都会察觉到这个更改 。本地通信因为所有进程共享同一块内存 , 共享内存在各种进程间通信方式中具有最高的效率 。访问共享内存区域和访问进程独有的内存区域一样快 , 并不需要通过系统调用或者其它需要切入内核的过程来完成 。同时它也避免了对数据的各种不必要的复制 。
因为系统内核没有对访问共享内存进行同步 , 您必须提供自己的同步措施 。例如 , 在数据被写入之前不允许进程从共享内存中读取信息、不允许两个进程同时向同一个共享内存地址写入数据等 。解决这些问题的常用方法是通过使用信号量进行同步 。不过 , 我们的程序中只有一个进程访问了共享内存 , 因此在集中展示了共享内存机制的同时 , 我们避免了让代码被同步逻辑搞得混乱不堪 。
内存模型要使用一块共享内存 , 进程必须首先分配它 。随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中 。当完成通信之后 , 所有进程都将脱离共享内存 , 并且由一个进程释放该共享内存块 。
理解 linux 系统内存模型可以有助于解释这个绑定的过程 。在 Linux 系统中 , 每个进程的虚拟内存是被分为许多页面的 。这些内存页面中包含了实际的数据 。每个进程都会维护一个从内存地址到虚拟内存页面之间的映射关系 。尽管每个进程都有自己的内存地址 , 不同的进程可以同时将同一个内存页面映射到自己的地址空间中 , 从而达到共享内存的目的 。
分配一个新的共享内存块会创建新的内存页面 。因为所有进程都希望共享对同一块内存的访问 , 只应由一个进程创建一块新的共享内存 。再次分配一块已经存在的内存块不会创建新的页面 , 而只是会返回一个标识该内存块的标识符 。一个进程如需使用这个共享内存块 , 则首先需要将它绑定到自己的地址空间中 。这样会创建一个从进程本身虚拟地址到共享页面的映射关系 。当对共享内存的使用结束之后 , 这个映射关系将被删除 。当再也没有进程需要使用这个共享内存块的时候 , 必须有一个(且只能是一个)进程负责释放这个被共享的内存页面 。
所有共享内存块的大小都必须是系统页面大小的整数倍 。系统页面大小指的是系统中单个内存页面包含的字节数 。在 Linux 系统中 , 内存页面大小是4KB , 不过您仍然应该通过调用 getpagesize 获取这个值 。
分配进程通过调用shmget(Shared Memory GET , 获取共享内存)来分配一个共享内存块 。
该函数的第一个参数是一个用来标识共享内存块的键值 。彼此无关的进程可以通过指定同一个键以获取对同一个共享内存块的访问 。不幸的是 , 其它程序也可能挑选了同样的特定值作为自己分配共享内存的键值 , 从而产生冲突 。用特殊常量IPC_PRIVATE作为键值可以保证系统建立一个全新的共享内存块 。
该函数的第二个参数指定了所申请的内存块的大小 。因为这些内存块是以页面为单位进行分配的 , 实际分配的内存块大小将被扩大到页面大小的整数倍 。
第三个参数是一组标志 , 通过特定常量的按位或操作来shmget 。这些特定常量包括:
IPC_CREAT:这个标志表示应创建一个新的共享内存块 。通过指定这个标志 , 我们可以创建一个具有指定键值的新共享内存块 。
IPC_EXCL:这个标志只能与 IPC_CREAT 同时使用 。当指定这个标志的时候 , 如果已有一个具有这个键值的共享内存块存在 , 则shmget会调用失败 。也就是说 , 这个标志将使线程获得一个“独有”的共享内存块 。如果没有指定这个标志而系统中存在一个具有相同键值的共享内存块 , shmget会返回这个已经建立的共享内存块 , 而不是重新创建一个 。
模式标志:这个值由9个位组成 , 分别表示属主、属组和其它用户对该内存块的访问权限 。其中表示执行权限的位将被忽略 。指明访问权限的一个简单办法是利用<sys/stat.h>中指定 , 并且在手册页第二节stat条目中说明了的常量指定 。例如 , S_IRUSR和S_IWUSR分别指定了该内存块属主的读写权限 , 而 S_IROTH和S_IWOTH则指定了其它用户的读写权限 。下面例子中shmget函数创建了一个新的共享内存块(当shm_key已被占用时则获取对一个已经存在共享内存块的访问) , 且只有属主对该内存块具有读写权限 , 其它用户不可读写 。
推荐阅读
- 谁才是“酱中之王”?黄豆酱、甜面酱、豆瓣酱,网友:它当之无愧
- 老茶收藏需知,只有今天的好茶才是将来的老茶
- 好茶有四个标准 怎样的茶才是最好的呢
- 虚拟内存结构了解一下
- 让小白也能看明白,什么才是专业的家庭影院功放
- PHP内存管理机制与垃圾回收机制
- 怎样喝茶才是最优雅科学的
- 原生态无污染才是真正农家茶
- 智能电视两大系统UI对比,原来系统体验好和无广告才是重中之重
- 手机内存不足怎么破?