效率: 采用共享内存通讯的一个显而易见的好处是效率高,由于进程能够直接读写内存,而不须要任何数据的拷贝。对于像管道和消息队列等通讯方式,则须要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]: 一次从输入文件到共享内存区,另外一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不老是读写少许数据后就解除映射,有新的通讯时,再从新建 立共享内存区域。而是保持共享区域,直到通讯完毕为止,这样,数据内容一直保存在共享内存中,并无写回文件。共享内存中的内容每每是在解除映射时才写回 文件的。所以,采用共享内存的通讯方式效率是很是高的。函数
共享内存没有任何的同步与互斥机制,因此要使用信号量来实现对共享内存的存取的同步ui
shmget函数spa
shmget函数建立一个新的共享内存区,或者访问一个已存在的共享内存区。操作系统
#include <sys/shm.h>.net
int shmget (key_t key, size_t size, int oflag) ;unix
返回值是一个称为共享内存区标识符的整数,其余三个shmXXX函数就用它来指代这个内存区。指针
参数key既能够是ftok的返回值,也能够是IPC_PRIVATE。系统创建IPC通信 ( 消息队列、 信号量和 共享内存) 时必须指定一个ID值。一般状况下,该id值经过ftok函数获得,由内核变成标识符,要想让两个进程看到同一个信号集,只需设置key值不变就能够。blog
参数size是指定内存区的大小。(若访问已存在的内存区,则size应为0),它的值通常为一页大小的整数倍(未到一页,操做系统向上对齐到一页,可是用户实际能使用只有本身所申请的大小)。队列
参数oflag是读写权限值的组合。建立一个新的共享内存,将shmflg 设置了IPC_CREAT标志后,共享内存存在就打开。而IPC_CREAT | IPC_EXCL则能够建立一个新的,惟一的共享内存,若是共享内存已存在,返回一个错误。通常咱们会还或(‘|’)上一个文件权限进程
当实际操做为建立一个新的共享内存区时,该内存区被初始化为size字节的0。
shmat函数
由shmget函数建立或打开一个共享内存区后,经过调用shmat把它附接到调用进程的地址空间。
#include <sys/shm.h>
void* shmat (int shmid, const void* shmaddr, int flag) ;
参数shmid是由shmget返回的标识符。
shmat的返回值是所指定的共享内存区在调用进程内的起始地址。(通常把参数shmaddr置为NULL,让系统替调用者选择地址)
参数flag能够指定SHM_RDONLY值,它限定只读访问。(默承认同时读写)一般为0.
shmdt函数
当一个进程完成某个共享内存区的使用时,它能够调用shmdt断接这个内存区。
#include <sys/shm.h>
int shmdt (const void* shmaddr) ;
参数addr是之前调用shmat时的返回值
当一个进程终止时,它当前附接着的全部共享内存区都自动断接掉。
注意,本函数只是断开关联,并不删除所指定的共享内存区。删除工做经过以IPC_RMID命令调用shmctl完成。(XSI IPC都是随内核持续的)
shmctl函数
shmctl提供了对一个共享内存区的多种操做。
#include <sys/shm.h>
int shmctl (int shmid, int cmd, struct shmid_ds* buff) ;
参数cmd:
IPC_RMID 从系统中删除该共享存储段。由于每一个共享存储段有一个链接计数器,因此除非使用该段的最后一个进程终止或与该段脱接,不然不会实际上删除该存储段。但无论此段是否仍在使用,该段标识符当即被删除,因此不能再用shmat与该段链接
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
转自:https://blog.csdn.net/ctthuangcheng/article/details/9271431
实践经验:unix内核并不像格式化磁盘同样格式化共享内存,因此用户必须人为的把大共享内存划分为单个的小记录块。
常见应用模型:
1. 1-1模型