您的位置:首页 > 运维架构 > Linux

Linux的进程编程-之二-进程间通信(共享内存)

2012-01-02 17:09 274 查看

1.1 共享内存

共享内存是最有用,也是最快的IPC方式。有三种实现共享内存的方法:系统调用mmap( )、POSIX共享内存、系统V共享内存。

三者都是先将文件映射到物理内存页面中,然后各个进程再把物理内存页面映射到本进程的地址空间中,从而实现进程间通信。所不同的是mmap( )映射的是普通文件;而系统V映射的是特殊文件系统shm中的文件,文件系统shm安装在交换分区上,系统重启后,shm的内容会丢失。

文件被映射到内存后,进程可以像访问内存一样对文件进行访问,不必再使用read( ),write( )等函数。由于多个进程共享内存,所以需要某种同步机制,如互斥锁、信号灯等。

1.1.1 系统调用共享内存

1.在Linux中,内存是以页为基本单位的,即使映射文件只有一个字节大小,内核在映射时也会分配一个页面大小的内存。

2.所有对共享内存的操作只在共享内存中有意义,只有在munmap( )或msync( )后,才能把共享内存中的内容写入文件。

1.1.1.1 mmap( )

#include<sys/mman.h>

void*mmap ( void * addr, size_t len , int prot , int flags , int fd , off_t offset )

#include<unistd.h>

longint sysconf( int name )

intgetpagesize( void ) = sysconf(_SC_PAGE_SIZE)

成功返回内存地址,失败返回(void*)-1。

addr :用户希望映射到当前进程地址空间中的内存地址;如果是NULL,由系统完成映射

fd :文件描述符,可以为-1,此时参数flags必须指定MAP_ANONYMOUS

len :文件映射到内存的字节数

offset :一般设为0,表示从文件起始处开始映射,应该是页面大小的整数倍

prot :内存访问权限:PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE

flags :

MAP_ ANONYMOUS :匿名映射,忽略fd和offset,用于具有亲缘关系的进程间通信

MAP_SHARED :对内存的更改能够影响文件(但要通过msync( )或munmap( )写入)

MAP_PRIVATE :对内存的更改不能影响文件,只在当前进程可见

MAP_FIXED :必须映射到指定的内存地址

MAP_LOCKED :锁定映射的内存



1.1.1.2 munmap( )

#include<sys/mman.h>

intmunmap( void * addr, si ze_t len )

取消[addr,addr+len-1]内涉及到的所有映射;成功返回0,失败返回-1。

注意:当进程结束时,映射会自动被取消。

1.1.1.3 mprotect( )

#include<sys/mman.h>

intmprotect( void *addr, size_t len, int prot )

更改[addr,addr+len-1]内涉及到的所有映射的访问权限;成功返回0,失败返回-1。

1.1.1.4 msync( )

#include<sys/mman.h>

intmsync ( void * addr , size_t len, int flags )

同步内存和文件;成功返回0,失败返回-1。

参数flags可以取:

MS_ASYNC :立即返回,写入操作异步进行

MS_SYNC :直到写入操作完成,才能返回

MS_INVALIDATE:刷新缓存,取消写入操作

1.1.1.5 mlock( )/munlock( ) / mlockall()/munlockall( )

注意:

1.内存可以被锁定多次,但只要一次解锁就可以完成解锁操作;

2.由于每个进程会将文件映射到自己的进程空间里面去,所以当前进程的内存解锁操作,并不影响其它进程的内存锁定操作;

#include<sys/mman.h>

intmlock( const void * addr, size_t len )

intmunlock( const void * addr, size_t len )

锁定[addr,addr+len-1]内涉及到的所有映射内存;成功返回0,失败返回-1。

#include<sys/mman.h>

int mlockall( int flags )

int munlockall( void )

锁定当前进程地址空间中的所有映射内存;成功返回0,失败返回-1。

参数flags可以取:

MCL_CURRENT:锁定当前进程地址空间中的所有映射内存。

MCL_FUTURE:不但锁定当前进程地址空间中的映射内存,之后新建的映射内存也被锁定。

1.1.2 系统V共享内存

1.1.2.1 ftok( )

#include<sys/types.h>

#include<sys/ipc.h>

key_tftok( const char *name, int id )

参数name指定了文件名(包含路径),该文件必须存在,而且当前进程必须能够访问该文件。

参数id只有低8位有效。

只有当name和id取值都相同时,返回的键值key才是相同的。

成功返回键值,失败返回-1。

1.1.2.2 shmget( )

#include<sys/ipc.h>

#include<sys/shm.h>

intshmget( key_t key, size_t size, int shmflg )

获得或创建一个共享内存;成功返回和键值key相关联的共享内存id,失败返回-1。

参数shmflg可以取IPC_CREAT、IPC_EXCL、IPC_NOWAIT。

单独使用IPC_CREAT,如果不存在与键值key相关联的共享内存,就创建一个新的共享内存,并返回其id,如果已经存在与键值key相关联的共享内存,就返回该共享内存的id。

单独使用IPC_EXCL是没有意义的,如果IPC_EXCL和IPC_CREAT一起使用,当与键值key相关联的共享内存已经存在时,就失败返回-1。

下面两种情况会创建一个新的共享内存:

1.参数shmflg指定IPC_CREAT,而且没有共享内存与键值key相关联;

2.参数key指定IPC_PRIVATE;

参数shmflg的低9位指定新创建共享内存的访问权限:

所有者
组成员
其他成员


执行


执行


执行

1.1.2.3 shmat( )

#include<sys/types.h>

#include<sys/shm.h>

void*shmat( int shmid, const void *shmaddr, int shmflg )

映射共享内存到当前进程的地址空间,成功返回映射地址,失败返回(void*)-1。

参数shmaddr指定映射到当前进程地址空间的位置,如果为NULL,系统自动进行映射。

参数shmflg可以取:

SHM_RDONLY:共享内存只读,默认可读写。

1.1.2.4 shmdt( )

#include<sys/types.h>

#include<sys/shm.h>

intshmdt( const void *shmaddr )

取消共享内存到当前进程的地址空间的映射;成功返回0,失败返回-1。

1.1.2.5 shmctl( )

#include<sys/types.h>

#include<sys/shm.h>

intshmctl( int shmid, int cmd, struct shmid_ds *buf )

获取或设置共享内存的属性;成功返回0,失败返回-1。

参数cmd可以指定三种操作:

IPC_STAT :获取共享内存的属性,返回的信息存放到buf指向的shmid_ds结构中。

IPC_SET :设置共享内存的属性,设置的信息存放在buf指向的shmid_ds结构中。

IPC_RMID :删除指定的共享内存。

1.1.3 Posix共享内存

1.1.3.1 shm_open()

#include<sys/mman.h>

int shm_open( const char *name, int flags, mode_t mode )

参数name指定与共享内存相关联的名字;成功返回共享内存描述符,失败返回-1。

参数flags可以取:

O_RDONLY O_RDWR(二选一)

O_CREAT

单独使用O_CREAT,如果name指定的共享内存不存在,就创建该共享内存,并返回其描述符;如果name指定的共享内存已经存在,就返回该共享内存的描述符。如果指定了O_CREAT,参数mode指定了新创建共享内存的访问权限。

用户
组成员
其他成员
S_IXUSR
100

S_IXGRP
010

S_IXOTH
001

S_IWUSR
200

S_IWGRP
020

S_IWOTH
002

S_IRUSR
400

S_IRGRP
040

S_IROTH
004

S_IRWXU
700

S_IRWXG
070

S_IRWXO
007

O_EXCL

单独使用O_EXCL是没有意义的,如果O_EXCL和O_CREAT一起使用,当name指定的共享内存已经存在时,就失败返回。

O_TRUNC

清空文件内容,如果同时满足以下条件:共享内存已经存在,而且在参数flags指定支持写操作(O_WRONLY)。

1.1.3.2 shm_unlink( )

#include<sys/mman.h>

intshm_unlink( const char * name )

成功返回0,失败返回-1。

删除指定的共享内存,但是如果当前仍有其它进程正在使用该共享内存,则暂时放弃删除操作,并立即返回,直到其它进程通过调用shm_unlink( )删除之后,再进行删除操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐