一 概述:
(一)共享内存区是最快的IPC形式。
*一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传递就不在涉及内核,然而往该内存区存放信息或从中取走信息的进程间需要同步。
(二)无亲缘关系进程间共享内存区的两种方法(注意步骤):
1.内存映射文件(父子进程或无亲缘关系都可):由open函数打开,由mmap函数把得到的描述符映射到当前进程地址空间的一个文件。
2.共享内存区对象:由shm_open打开一个Posix IPC名字,所返回的描述符由mmap函数映射到当前进程的地址空间。
二 相关函数:
(1)mmap函数:
*作用:使用普通文件以提供内存映射IO;使用特殊文件以提供匿名内存映射;使用shm_open以提供无亲缘关系进程间POSIX共享内存区。
void *mmap(void *addr,size_t len,int prot,int flags,int fd,off_t offset):返回值
*addr:指定描述符fd应被映射到的进程内空间的起始地址。通常为空指针,告诉内核自己去选择起始地址。返回值为描述符fd所映射到内存区的起始地址。
*len是映射到调用进程地址空间的字节数,它从被映射文件头部起offset个字节处开始算。offset通常设为0.
*prot:指定内存映射区的保护。使用如下常值,该参数的常见值是代表读写访问的PROT_READ|PROT_WRITE。
*flags:使用下图中的常值指定。MAP_SHARED或MAP_PRIVATE必须指定一个,并可选择的或上MAP_FIXED。
(2)父子进程之间共享内存区的方法之一是:父进程在调用fork前先指定MAP_SHARED调用mmap。
(3)munmap:从进程的地址空间删除一个映射关系。
int munmap(void *addr,size_t len)
*addr:由mmap返回的地址。
*len:是映射区的大小。
*再次访问这些地址将导致向调用进程产生一个SIGSEGV信号。
*如果被映射区是使用MAP_PRIVATE标志映射的,那么调用进程对它所做的变动都将被丢弃掉。
(4)msync函数:确保硬盘上的文件内容与内存映射区中的内容一致。
*msync(void *addr,size_t len,int flags):addr和len知道内存中的整个内存映射区或该内存区的一个子集。
*flags:MS_ASYNC和MS_SYNC两个常值必须指定一个,但不能都指定。差别:一旦写操作已由内核排入队列,MS_ASYNC则返回,而MS_SYNC则要等到写操作完成后才返回。
三 Posix共享内存区:
(1)Posix共享内存区的步骤:
*指定一个名字参数调用shm_open,以创建一个新的共享内存区对象或打开一个已存在的共享内存区对象。
*调用mmap把这个共享内存区映射到调用进程的地址空间。
(2)相关函数:
1.shm_open:创建一个新的共享内存区对象或打开一个已存在的共享内存区对象。
int shm_open(const char *name,int oflag,mode_t mode):返回值所谓mmap函数的第五个参数。
2.shm_unlink:删除一个共享内存区对象的名字。与所有其他unlink函数(删除文件系统中一个路径名的unlink,删除一个Posix消息队列的mq_unlink,以及删除一个Posix有名信号量的sem_unlink)一样,删除一个名字不会映射对于其底层支持对象的现有引用,直到对于该对象的引用全部关闭为止。删除一个名字仅仅是防止后续的open、mq_open或sem_open调用成功。
3.ftruncate:修改普通文件或共享内存区对象的大小。
*int ftruncate(int fd,off_t length)
~对于普通文件:如果文件的大小大于length参数,额外的数据就被丢弃掉。如果小于length,那么该文件大小是否增长是未说明的。
~对于一个共享内存区对象:ftruncate把该对象的大小设置为length字节。
*fstat:获取打开的文件或已存在的共享内存区对象的相关信息。