linux编程之共享内存
linux 进程间通信(IPC)包括3种机制:消息队列、信号量、共享内存。消息队列和信号量均是内核空间的系统对象,经由它们
的数据需要在内核和用户空间进行额外的数据拷贝;而共享内存和访问它的所有应用程序均同处于用户空间,应用进程可以通过地址
映射的方式直接读写内存,从而获得非常高的通信效率。在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程
接口API允许一个进程使用公共内存区段。 如果使用消息队列进行通信,那么一个进程要向队列中写入消息,这要引起从用户地址空
间向内核地址空间的一次复制,同样一个进程进行消息读取时也要进行一次复制,而共享内存的优点是完全省去了这些操作。两个不
同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数
据的更新,反之亦然,因此通过共享内存映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。由于多个进程
共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量
共享内存区的相关操作:
使用共享内存的流程:
1.进程必须首先分配它。
2.随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中。
3.当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块。
#include <sys/ipc.h>
#include <sys/shm.h>
/*
创建一个新的内存共享区或者访问一个已经存在的共享内存区
返回共享内存区标识符
*/
int shmget(key_t key, size_t size, int shmflg);
/*
创建或打开一个共享内存区后,调用shmat把它连接到调用进程的地址空间
*/
void *shmat(int shmid, const void *shmaddr,int shmflg);
/*
当一个进程完成某个共享内存区的使用时,调用shmdt断开这个内存区
*/
int shmdt(const void *shmaddr);
/*
对内存区进行多种操作
cmd取值:
IPC_RMID:从系统中删除由shmid标识的共享内存区并拆除它
IPC_SET:给指定的共享内存区设置其shmid_ds结果成员
IPC_STAT:通过buff参数向调用者返回所指定共享内存区当前的shmid_ds结构
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
#include<sys/types>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmget(key_t key, size_t size, int shmflg );
参数:
key:ftok返回值或者IPC_PRIVATE
size:共享内存区大小( 字节为单位,if访问一个已经存在的,那么就是0 )
oflag:权限的组合
shmget()函数用于创建一个新的共享内存段,或者访问一个现有的共享内存段,它与消息队列以及信号集合对应的函数十分相似.如
果shmflg只为IPC_CREAT,shmget()或者将返回新创建的内存段标识符,或者返回早已存在于内核中的具有的相同关键字值(key)
的内存段的标识符;如果其同时为IPC_CREAT和IPC_EXCL,则如果该内存段不存在就创建一个新的内存段,如果早已存在,则此时
调用失败,并将返回-1.
#include<sys/types>
#include<sys/ipc.h>
#include<sys/shm.h>
void *shmat(int shmid,const void *shmaddr,int shmflg);
int shmdt(const void *shmaddr);
函数shmat()用来获取共享内存的地址,获取成功后,就可以像使用普通内存一样对其进行读写操作。
#include<sys/types>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmdt(const void *shmaddr);
当某一个进程不再需要一个共享内存段时,它必须调用这个函数来断开与该内存段的连接
#include<sys/types>
#include<sys/ipc.h>
#include<sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
共享内存控制函数,它的使用类似ioctl()的方式对共享内存进行操作:向共享内存的句柄发送命令,来完成某种命令
对于每个共享的内存区,内核维护如下的信息结构,定义在<sys/shm.h>头文件中。

1 struct shmid_ds {
2 struct ipc_perm shm_perm; /* operation perms */
3 int shm_segsz; /* size of segment (bytes) */
4 time_t shm_atime; /* last attach time */
5 time_t shm_dtime; /* last detach time */
6 time_t shm_ctime; /* last change time */
7 unsigned short shm_cpid; /* pid of creator */
8 unsigned short shm_lpid; /* pid of last operator */
9 short shm_nattch; /* no. of current attaches */
10 /* the following are private */
11 unsigned short shm_npages; /* size of segment (pages) */
12 unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
13 struct vm_area_struct *attaches; /* descriptors for attaches */
14 };

这里有点要注意,当我们调用shmdt()来删除共享内存段时,只是断开该进程与这个内存段的连接,而此时内核不一定就删除内存段,
结合上述,在成功完成了断开连接操作后,相关的shmid_ds结构的shm_nattch成员的值将减去1,如果这个值减到0,则内核将真正
删除该内存段。
linux编程之共享内存的更多相关文章
- Linux信号量同步共享内存实验.
Linux信号量同步共享内存实验. Linux信号量同步共享内存实验. 简述 程序流程 信号量和共享内存的系统函数 信号量系统函数及接口 共享内存系统函数及接口 写程序 读程序 简述 本文主要内容是自 ...
- Linux环境进程间通信: 共享内存
Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...
- Linux IPC之共享内存C 事例
Linux IPC之共享内存 标签: linuxrandomnull工作 2011-08-25 11:52 4123人阅读 评论(0) 收藏 举报 分类: Linux(3) 读书札记(3) 版权 ...
- Linux进程间通信—使用共享内存
Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内 ...
- Linux环境编程之共享内存区(一):共享内存区简单介绍
共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...
- linux网络编程之共享内存介绍
今天是个好日子,洋人之节乃全球同庆,圣诞一来感觉就要过年了,不过今晚心情有点打折扣,给心爱的人打电话没有打通,本想在平安夜送上快乐的祝福给她,糟糕的心情让自己好像泄了气的皮球一样,无精打彩,心情灰暗, ...
- Linux IPC POSIX 共享内存
模型 #include <unistd.h> //for fstat() #include <sys/types.h> //for fstat() #include <s ...
- Linux进程间通信之共享内存
一,共享内存 内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即共享内存. 映射物理内存叫挂接,用完以后解除映射叫脱接. 1,共享内存的特点 ...
- Linux进程间通信——使用共享内存
一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...
随机推荐
- MYsql 数据库密码忘记(Window)-2(mysql 5.7)
很久没用Mysql了,再次打开,发现用不了了,密码忘了,服务也无法打开,在cmd中输入mysql之后,显示不是内部指令. 看来问题是mysql服务打不开了 (1)在cmd中 输入net start m ...
- Runtime介绍
本文目录 1.Runtime简介 2.Runtime相关的头文件 3.技术点和应用场景 3_1.获取属性\成员变量列表 3_2.交换方法实现 3_3.类\对象的关联对象,假属性 3_4.动态添加方法, ...
- 【刷题】洛谷 P2709 小B的询问
题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...
- HDU 1535 SPFA 前向星存图优化
Invitation Cards Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- [mysql]mysql弱密码字典检测
1.如何定义弱密码 和用户名一致 连续字符 连续数字 空密码 2.生成弱密码字典 3.检测脚本 4.结果
- [linux/net]策略路由实现特定主机特定路径
echo 200 silence >> /etc/iproute2/rt_tables ip rule add from 10.192.0.230 table silence ip ...
- C#学习之泛型继承和静态成员
想要理解这里有必要先将泛型类学习充分.这里讲解的是泛型类继承类的类型和静态成员. 在前面C#学习之泛型中,创建的LinkList<T>类实现了IEnumerable<T>接口. ...
- Moodle配置
Moodle配置 1. 内部设置 在 Moodle 站点管理员界面中有一系列的配置页面(可以从'设置' 块中访问 '网站管理'区).这里有一些重要的系统设置,你需要进行检查. 根据提示信息并结合实 ...
- redis 选择数据库
redis 127.0.0.1:6379> SELECT 1 # 使用 1 号数据库
- UVA 11040 Add bricks in the wall
https://vjudge.net/problem/UVA-11040 找规律 #include<cstdio> using namespace std; ][]; int main() ...