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

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

共享内存有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. Deploying Docker images via SSH

    Original URL:https://advancedweb.hu/2015/04/14/deploying-docker-images-via-ssh/ Background When we b ...

  2. NodeJS待重头收拾旧山河(重拾)

    介绍 Node.js®是一个基于Chrome V8 JavaScript引擎构建的JavaScript运行时. Node.js使用事件驱动的非阻塞I / O模型,使其轻便且高效. Node.js的包生 ...

  3. python实现区块链代码

    如果你明白了原理其实挺简单的. 加密算法是python自带的 需要导入hashlib import hashlib as hash sha = hasher.sha256() sha.update(' ...

  4. Ubuntu下配置Nginx HTTPS

    HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP下加入S ...

  5. 处理字符串的一些C函数

    注意:以下函数都包含在ctype.h头文件中 1.isalpha函数 用来判断得到的参数是不是字母 #include<stdio.h> #include<ctype.h> in ...

  6. 触发器 (Delete Update)

    --delete触发器IF(EXISTS(SELECT * FROM sysobjects WHERE name='T_PlanQtyDelete'))DROP TRIGGER T_PlanQtyDe ...

  7. Net dll版本兼容问题

    Net dll组件版本兼容问题 https://www.cnblogs.com/newP/p/9543528.html dll组件版本兼容问题,是生产开发中经常遇到的问题,常见组件兼容问题如:Newt ...

  8. Java过滤特殊字符

    Java正则表达式过滤 1.Java过滤特殊字符的正则表达式----转载 java过滤特殊字符的正则表达式[转载] 2010-08-05 11:06 Java过滤特殊字符的正则表达式   关键字: j ...

  9. Appium python Uiautomator2 多进程问题

    appium更新uiautomator后可以获取tost了,大家都尝试,课程中也讲解了,但是这些跑的时候都在单机上,当我们多机并发的时候会出现一个端口问题,因为我们appium最后会调用uiautom ...

  10. 深入Asyncio(九)异步生成器

    Async Generators:yield inside async def functions 如果在async def中使用yield会发生什么,答案就是生成一个异步生成器函数,如果有生成器.协 ...