系统调用和System V共享内存
(一) 介绍
管道和消息队列等通信方式,需要在内核和用户空间进行四次的数据拷贝;而共享内存只拷贝两次数据,一次从输入文件到共享内存区,另一次从共享内存区到输出文件;进程之间在共享内存时,一直保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。Linux内核支持多种共享内存方式,如mmap()系统调用,Posix共享内存,以及System V共享内存。linux发行版本支持mmap()系统调用及System V共享内存,但还没实现Posix共享内存.
(二)系统调用mmap()
系统调用使得进程之间通过映射同一个普通磁盘文件实现共享内存。如果采用MAP_SHARE共享内存,则对映射区域的写入数据会复制回磁盘文件内,而且允许其他映射该文件的进程共享, 原来的文件会改变。Mmap最大的优势,就是映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写操作,如常通过strxxx,memxxx函数完成,不必再调用read,write等系统调用.但需注意,直接对该段内存写时不会写入超过当前文件大小的内容.函数原型void* mmap ( void * addr , size_t len
, int prot , int flags , int fd , off_t offset ) ;函数入参:Fd:即将映射到进程空间的文件描述符,可见要用fd,必须在open一个磁盘文件返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信);Len:映射到进程地址空间的字节数,它从被映射磁盘文件开头offset个字节开始算起Prot:指定共享内存的访问权限。可取如下几个值的或:PROT_READ(页可读)
, PROT_WRITE (页可写), PROT_EXEC (页可执行), PROT_NONE(页不可访问),默认页大小4K,所以len最好为4K整数倍,并且要注意与磁盘文件权限的匹配;Flag:由以下几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用Offset: 一般设为0,表示从文件头开始映射;Addr: 指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。函数返回值: 最后文件映射到进程空间的地址;