码迷,mamicode.com
首页 > 其他好文 > 详细

IPC: 共享内存

时间:2015-02-28 21:47:01      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:mman

###################################################

共享内存区

 

共享内存是IPC形式中最快的,因为共享内存不和内核进行数据交换。

 

通过fork派生的子进程不与父进程共享内存区。

 

共享内存区分为:

1.posix共享内存区

2.system V共享内存区

 

共享内存有两种形式:

1.匿名共享内存

2.有名共享内存

 

-----------------------------------------------------------

posix共享内存区:

 

gcc -lrt

 

-----------------------

系统调用

#include <sys/mman.h>

 

内存映射文件:就是硬盘中的文件或posix的共享内存区对象。

内存映射区:就是进程的地址空间,也就是内存中的内容。

 

void *mmap(void *addr, size_t length, int prot, intflags, int fd, off_t offset)

mmap把一个文件或posix共享内存区对象映射到调用进程的的地址空间;

成功返回该地址空间的起始地址,失败返回MAP_FAILED。

 

addr:内存映射区的起始地址,一般为NULL,让进程自己选择地址。

length:映射到进程地址空间的字节数。

offset:从内存映射文件的什么地方开始映射,一般是0.

 

fd就是内存映射文件:

1.用open打开文件

2.用shm_open打开文件

3.特殊参数=-1

 

prot:对内存映射区的保护,不能超过文件的打开权限。

PROT_READ:映射区可读

PROT_WRITE:映射区可写

PROT_EXEC:映射区可执行

PROT_NONE:映射区数据不可访问

 

flags:被映射的数据的标识,共享和私有必须指定一个。

MAP_SHARED:变动是共享的,除了修改的进程之外的其它进程也可见。

MAP_PRIVATE:变动是私有的,只有修改的进程可见。

MAP_ANONYMOUS:不用创建文件,fd=-1,offset=0,需MAP_SHARED

 

用mmap将硬盘文件映射到进程空间,不创建文件的两种方法:

1.用MAP_ANONYMOUS参数,fd=-1即可

2.使用/dev/zero作为文件,用open打开/dev/zero,返回fd

 

int munmap(void *addr, size_t length);

从进程的地址空间删除映射关系。

addr:由mmap返回的地址;

len:映射区的大小。

 

int mprotect(void *addr, size_t len, int prot);

更改现有内存映射区的权限,成功返回0,失败返回-1.

addr和len要和页边界对齐。

 

int msync(void *addr, size_t length, int flags);

如果存储映射区内容修改了,使用该函数将内容同步到内存映射文件中,成功返回0,失败返回-1.

如果映射是私有的就不修改文件。

addr和length要和页边界对齐。

 

flags:指定同步标识,同步和异步必须且只能指定一个。

MS_ASYNC:执行异步写

MS_SYNC:执行同步写

MS_INVALIDATE:使高速缓存的数据失效

 

-----------

#include<unistd.h>

#include <sys/types.h>

int ftruncate(int fd, off_t length);

用来截取内存映射文件或共享内存区的大小。

 

#include<unistd.h>

#include<sys/stat.h>

#include<sys/types.h>

int fstat(int fd, struct stat *buf);

获取内存映射文件的信息。

 

当fd为一个共享内存区对象时,只有下列四个参数有意义:

struct stat {

    mode_t st_mode;

    uid_t st_uid;

    gid_t st_gid;

    off_t st_size; // 文件大小

};

 

-----------------------

库函数

#include <sys/mman.h>

#include <sys/stat.h>

#include <fcntl.h>

 

int shm_open(const char *name, int oflag, mode_t mode);

oflag不能指定O_WRONLY参数,且mode参数必须指定。

效果和open函数差不多,返回一个描述符fd作为mmap的fd参数。

 

int shm_unlink(const char *name);

删除一个共享内存区对象的名字。

 

-----------------------------------------------------------

system v共享内存区:

 

#include <sys/ipc.h>

#include <sys/shm.h>

#include <sys/types.h>

 

内核维护一个共享内存结构:

struct shmid_ds {

    struct ipc_permshm_perm;

    size_t shm_segsz;//共享内存大小

    pid_t shm_lpid;//最后一个操作的pid

    pid_t shm_cpid;//创建者的pid

    shmatt_t shm_nattch;

    shmat_t shm_cnattch;

    time_t shm_atime;

    time_t shm_dtime;

    time_t shm_ctime;

};

 

int shmget(key_t key, size_tsize, int shmflg);

创建一个新的共享内存区,或者访问一个已经存在的共享内存区。返回共享内存区标识符。

 

key:既可以是ftok的返回值,也可以是IPC_PRIVATE.

 

size:以字节为单位,指定内存区的大小,如果是已存在的共享内存区,为0.

 

shmflg:

shmflg: 可以用读写权限 或 其它可选权限。

属主:SHM_R        SHM_A

属组:SHM_R >> 3   SHM_A >> 3

其它:SHM_R >> 6   SHM_A >> 6

IPC_CREAT:不存在就创建,存在就返回已存在的。

IPC_CREAT | IPC_EXCL:不存在就创建,存在就返回错误。

 

void *shmat(int shmid, constvoid *shmaddr, int shmflg);

把已经创建的共享内存区映射到调用进程的地址空间,返回起始地址。

 

shmaddr:一般为NULL,让系统自己选择地址。

 

shmflg:一般为0.

SHM_RND:如果shmaddr不为空,映射到shmaddr指定的地址向下舍入SHMLBA个值的地方,如果没有这个标识就映射到shmaddr指定的地方。

SHM_RDONLY:只读访问

 

int shmdt(const void *shmaddr);

断开已存在的共享内存区和进程的地址空间的映射关系。

 

int shmctl(int shmid, int cmd,struct shmid_ds *buf);

对共享内存区的操作。

 

cmd:

IPC_STAT:获取共享内存段的值

IPC_SET:设置共享内存段的值

IPC_RMID:删除共享内存段

IPC_INFO

SHM_INFO

SHM_STAT

SHM_LOCK

SHM_UNLOCK

 

###################################################

IPC: 共享内存

标签:mman

原文地址:http://blog.csdn.net/wowotouweizi/article/details/43988645

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!