码迷,mamicode.com
首页 > 系统相关 > 详细

linux 进程学习笔记-共享内存

时间:2015-11-23 14:43:59      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:

如果能划定一块物理内存,让多个进程都能将该内存映射到其自身虚拟内存空间的话,那么进程可以通过向这块内存空间读写数据而达到通信的目的。另外,和消息队列不同的是,共享的内存在用户空间而不是核空间,那么就不存在“用户空间和内核空间之间数据复制”的问题,这会减少不少开销。 

由于不同进程都可能向同一个空间读写数据,所以其需要一些同步机制来防止混乱,可以使用的机制有“信号量”“文件锁”等。 

共享内存有mmap和System V Shared Memory, 下面说的是后者。 

  

创建或打开共享内存: 

int shmget(key_t key, size_t size, int shmflg); 

这与创建和打开消息队列的msgget非常类似,其同样用一个key_t类型的key来唯一标识被共享的内存。 size参数表示要创建的共享内存的大小,就像malloc函数一样。 shmflg参数和msgget函数的shmflg参数一样:其有两层含义,一是该参数可以取值IPC_CREATE,表示请求新建共享内存;也可以是 IPC_CREATE|IPC_EXCL的按位组合,表示请求新建共享内存但如果已经存在的话则报错。二是该参数表示权限控制,比如666表示全部可读写。那么如果该参数写成IPC_CREATE|IPC_EXCL|666则表示请求新建共享内存但如果已经存在的话则报错并且权限为666 

  

将共享内存attach到进程自己的虚拟内存空间: 


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

shmid参数: 

准备attach的共享内存id 

shmaddr参数: 

要将共享内存attach到的进程自己的虚拟空间地址,其需要和shmflg参数结合起来理解。 

1)如果该参数传递一个空指针的话,则共享内存将被attach到由系统自动选择的第一块可能内存 

2)如果该参数不为空: 

2.1)如果 shmflg & SHM_RND 不为0,那么共享内存将被attach到这个地址: 

(shmaddr -((uintptr_t)shmaddr %SHMLBA)).  

其中,SHM_RND标识表示取整对齐(round), SHMLBA是共享内存低段地址,也就是附加共享内存的边界地址。那么上面的计算公式意思是说:将shmaddr指定的地址移动到第边界地址的整数倍上。相反的,如果shmflg & SHM_RND为0,则直接使用shmaddr指定的地址。 

2.2)如果 (shmflg &SHM_RDONLY) 不为0,那么共享内存将变得只读(如果有读权限的话),相反的,(shmflg &SHM_RDONLY) 为0,则共享内存可读可写(如果有写权限的话) 

当attach成功后,共享内存在进程虚拟空间中的首地址将被返回,这时你就可以像操作普通内存一样来使用它了。 

  

attach的反向操作:将共享内存从进程的内存空间脱离 

int shmdt(const void *shmaddr); 

shmaddr参数就是原来attach上时的地址。 

  

共享内存所对应的数据结构(shmid_ds)和消息队列的数据结构(msqid_ds)非常的类似,相关操作也雷同: 


struct shmid_ds {
         struct ipc_perm         shm_perm;       /* operation perms */
         int                     shm_segsz;      /* size of segment (bytes) */
         __kernel_time_t         shm_atime;      /* last attach time */
         __kernel_time_t         shm_dtime;      /* last detach time */
         __kernel_time_t         shm_ctime;      /* last change time */
         __kernel_ipc_pid_t       shm_cpid;       /* pid of creator */
         __kernel_ipc_pid_t       shm_lpid;       /* pid of last operator */
         unsigned short          shm_nattch;     /* no. of current attaches */
         unsigned short          shm_unused;     /* compatibility */
         void                   *shm_unused2;   /* ditto - used by DIPC */
         void                   *shm_unused3;   /* unused */
 };
 
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

第一个参数表示要操作的共享内存的id 

cmd参数表示要执行的操作,与msgctl函数类似: 

1)IPC_STAT获取消息队列属性信息,并将这些信息放置到第3个参数所设置的buffer中 

2)IPC_SET 根据buffer中的数据设置消息队列的一些属性,并非所有属性都可设置,其仅仅限于:ipc_perm.uid,ipc_perm.gid,ipc_perm.mode 这几种 

3)IPC_RMID 删除消息队列。 

注:IPC_SET和IPC_RMID都会进行相应的权限检查,只有具备权限的进程才能执行相关操作 

 

linux 进程学习笔记-共享内存

标签:

原文地址:http://www.cnblogs.com/zendu/p/4988360.html

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