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

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

共享内存有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参数结合起来理解。 

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

)如果该参数不为空: 

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函数类似: )IPC_STAT获取消息队列属性信息,并将这些信息放置到第3个参数所设置的buffer中 )IPC_SET 根据buffer中的数据设置消息队列的一些属性,并非所有属性都可设置,其仅仅限于:ipc_perm.uid,ipc_perm.gid,ipc_perm.mode 这几种 )IPC_RMID 删除消息队列。 注:IPC_SET和IPC_RMID都会进行相应的权限检查,只有具备权限的进程才能执行相关操作

linux 进程学习笔记-共享内存的更多相关文章

  1. ubuntu linux c学习笔记----共享内存(shmget,shmat,shmdt,shmctl)

    shmget int shmget(key_t key, size_t size, int flag); key: 标识符的规则 size:共享存储段的字节数 flag:读写的权限 返回值:成功返回共 ...

  2. linux kernel学习笔记-5内存管理_转

    void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...

  3. Linux 进程通信(共享内存区)

    共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段). 如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中. 如果一个进程更新了段中的数据,其他进程也 ...

  4. linux 进程通信之 共享内存

    共享内存是被多个进程共享的一部分物理内存.共享内存是进程间共享数据的一种最快的方法.一个进程向共享内存区域写入了数据,共享这个内存区域的全部进程就能够立马看到当中的内容. 关于共享内存使用的API k ...

  5. linux进程学习笔记

    学习了linux下的进程,觉得应该整理一下,忘得差不多了,顺便回顾一下. 学而时习之,不亦说乎~~ 进程笔记 ,什么是进程? The Single UNIX Specification, Versio ...

  6. linux 进程学习笔记-进程调度

    在分时系统中,系统将CPU时间划分成无数个时间片(quantum)分配给不同的进程,一个时间片只执行一个进程,并且不停地切换,以让用户感觉到各个进程是在“同时运行”,这中间所需要的策略和算法便是进程调 ...

  7. linux进程通信之共享内存

    共享内存同意两个或多个进程共享一给定的存储区,由于数据不须要来回复制,所以是最快的一种进程间通信机制.共享内存能够通过mmap()映射普通文件(特殊情况下还能够採用匿名映射)机制实现,也能够通过系统V ...

  8. linux 进程学习笔记-进程pipe管道

    所谓“进程间通信(IPC,inter-process communication)”,按照其目的讲就是让进程之间能够“共享数据”,“传输数据”,“事件通知”等,我所知道的一共有“管道” “信号” “消 ...

  9. linux 进程学习笔记-信号semaphore

    信号灯(信号量)不是进程通信手段,其是用于控制和协调在进程间通信过程中的共享资源访问,就如同互斥锁(两者的区别可以参考这里) 可以将简单地将信号灯想象成一个计数器,初始时计数器值为n(有n个资源可供使 ...

随机推荐

  1. WPF自定义依赖集合属性无法触发更新的问题

    通常WPF中通过继承UserControl的来快速创建自定义控件,最近项目上需要设计一个卫星星图显示控件,最终效果如下图所示.完成过程中遇到了自定义集合依赖属性无法触发更新通知的问题,在此记录一下,方 ...

  2. Java开启/关闭tomcat服务器

    © 版权声明:本文为博主原创文章,转载请注明出处 通过java代码实现Tomcat的开启与关闭 1.项目结构 2.CallTomcat.java package com.calltomcat.test ...

  3. 【BLE】CC2541之自己定义按键

    本篇博文最后改动时间:2017年01月06日,11:06. 一.简单介绍 本文以SimpleBLEPeripheral为例.介绍怎样将普通IO口(P12)自己定义为按键. 注:本文加入按键方法不与协议 ...

  4. Android Calendar的学习与运用

    [java]mport java.text.DateFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; ...

  5. Druid——阿里巴巴的开源项目(关于数据库连接、监控)

    相关文章 0.Druid首页——jdbc连接池,监控组件 1.阿里巴巴的开源项目Druid(关于数据库连接) 2.ITeye谈Druid 3.DBCP(DataBase connection pool ...

  6. PowerBuilder -- 指定重复的列不显示

  7. cocos2dx 3.2+ 项目创建与问题总汇

    本文为Cocos2d-x 3.x 全平台(Android,iOS)新手开发配置教程攻略,希望对大家有所帮助.由于这篇文章是面对新手的. 所以有些地方会啰嗦一些,请勿见怪. 假设教程中有错误.欢迎指正. ...

  8. 数据结构:最小生成树--Kruskal算法

    Kruskal算法 Kruskal算法 求解最小生成树的还有一种常见算法是Kruskal算法.它比Prim算法更直观.从直观上看,Kruskal算法的做法是:每次都从剩余边中选取权值最小的,当然,这条 ...

  9. Redis实现主从复制(转)

    一.Redis的Replication: 这里首先需要说明的是,在Redis中配置Master-Slave模式真是太简单了.相信在阅读完这篇Blog之后你也可以轻松做到.这里我们还是先列出一些理论性的 ...

  10. WCF基础之设计和实现服务协定

    本来前面还有一个章节“WCF概述”,这章都是些文字概述,就不“复制”了,直接从第二章开始. 当然学习WCF还是要些基础的.https://msdn.microsoft.com/zh-cn/hh1482 ...