Linux IPC 共享内存
共享内存
共享内存(shared memory)是最简单的Linux进程间通信方式之一。
使用共享内存,不同进程可以对同一块内存进行读写。
由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不需要进行额外系统调用或内核操作,同时还避免了多余的内存拷贝,所以,这种方式是效率最高、速度最快的进程间通信方式。
这种最大限度的自由也给共享内存带来了缺点:内核并不提供任何对共享内存访问的同步机制,比如 同时对共享内存的相同地址进行写操作,则后写的数据会覆盖之前的数据。所以,使用共享内存一般还需要使用其他IPC机制(如信号量)进行读写同步与互斥。
---------------------
基本原理
了解Linux内存管理机制,就很容易知道共享内存的原理了。
大家知道,内核对内存的管理是以页(page)为单位的,Linux下一般一个page大小是4k。
而程序本身的虚拟地址空间是线性的,所以内核管理了进程从虚拟地址空间到起对应的页的映射。
创建共享内存空间后,内核将不同进程虚拟地址的映射到同一个页面:所以在不同进程中,对共享内存所在的内存地址的访问最终都被映射到同一页面。下图演示了共享内存的工作机制
---------------------
相关接口
1)创建共享内存(SHared Memory GET):
int shmget(key_t key, int size, int flag);
返回:成功时返回一个和key相关的共享内存标识符,失败范湖范围-1。
key:为共享内存段命名,多个共享同一片内存的进程使用同一个key。
size:共享内存容量。
flag:权限标志位,和open的mode参数一样。
2)连接到共享内存地址空间(SHared Memory ATtach):
void *shmat(int shmid, void *addr, int flag);
返回:返回值即共享内存实际地址。
shmid:shmget()返回的标识。
addr:决定以什么方式连接地址。
flag:访问模式。
3)从共享内存分离(SHared Memory DeTach):
int shmdt(const void *shmaddr);
返回:调用成功返回0,失败返回-1。
shmaddr:是shmat()返回的地址指针。
/*
* a.c
* write a random number between 0 and 999 to the shm every 1 second
*/
#include<stdio.h>
#include<unistd.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<error.h>
int main(){
int shm_id;
int *share;
int num;
srand(time(NULL));
shm_id = shmget (, getpagesize(), IPC_CREAT);//shm_id 就是 # ipc -m 命令查询到的 linux中共享内存的keyid吧 注意运行结束后清理掉 使用ipcrm -m shm_id 清理
if(shm_id == -){
perror("shmget()");
}
share = (int *)shmat(shm_id, , );
while(){
num = random() % ;
*share = num;
printf("write a random number %d\n", num);
sleep();
}
return ;
}
/*
* b.c
* read from the shm every 1 second
*/
#include<stdio.h>
#include<unistd.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<error.h>
int main(){
int shm_id;
int *share;
shm_id = shmget (, getpagesize(), IPC_CREAT);
if(shm_id == -){
perror("shmget()");
}
share = (int *)shmat(shm_id, , );
while(){
sleep();
printf("%d\n", *share);
}
return ;
}
运行观察结果:
运行时候通过ipcs -m查看共享内存的id 的情况 记得要释放掉共享的内存 如果不释放 下次 还是会被占用!!!!!!
取得ipc信息:
ipcs [-m|-q|-s]
-m 输出有关共享内存(shared memory)的信息
-q 输出有关信息队列(message queue)的信息
-s 输出有关“遮断器”(semaphore)的信息
# ipcs -m
IPC status from as of 2007年04月10日 星期二 18时32分18秒 CST
T ID KEY MODE OWNER GROUP
Shared Memory:
m 0 0x50000d43 --rw-r--r-- root root
m 501 0x1e90c97c --rw-r----- Oracle dba
清理掉共享内存
# ipcrm 命令
移除一个消息对象。或者共享内存段,或者一个信号集,同时会将与ipc对象相关链的数据也一起移除。当然,只有超级管理员,或者ipc对象的创建者才有这项权利啦
ipcrm用法
ipcrm -M shmkey 移除用shmkey创建的共享内存段
ipcrm -m shmid 移除用shmid标识的共享内存段
ipcrm -Q msgkey 移除用msqkey创建的消息队列
ipcrm -q msqid 移除用msqid标识的消息队列
ipcrm -S semkey 移除用semkey创建的信号
ipcrm -s semid 移除用semid标识的信号
Linux IPC 共享内存的更多相关文章
- linux IPC共享内存
共享内存相关函数 获得一个共享存储标识符 #include <sys/ipc.h> #include <sys/shm.h int shmget(key_t key, size_t ...
- Linux进程间通信—共享内存
五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...
- linux 下共享内存
一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要 ...
- linux 进程间通信 共享内存 shmat
系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件(这是通过shm ...
- linux下共享内存mmap和DMA(直接访问内存)的使用 【转】
转自:http://blog.chinaunix.net/uid-7374279-id-4413316.html 介绍Linux内存管理和内存映射的奥秘.同时讲述设备驱动程序是如何使用“直接内存访问” ...
- 学习笔记:Linux下共享内存的方式实现进程间的相互通信
一.常用函数 函数系列头文件 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> ft ...
- linux 进程间通信 共享内存 mmap
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反 ...
- IPC——共享内存
Linux进程间通信——使用共享内存 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的 ...
- linux使用共享内存通信的进程同步退出问题
两个甚至多个进程使用共享内存(shm)通信,总遇到同步问题.这里的“同步问题”不是说进程读写同步问题,这个用信号量就好了.这里的同步问题说的是同步退出问题,到底谁先退出,怎么知道对方退出了.举个例子: ...
随机推荐
- Luogu 2322 [HNOI2006]最短母串问题
唔,太菜了,弄了好几个小时. 状压dp,设$f_{s, i}$表示选了集合$s$,以$i$结尾的最短长度,设$g_{i, j}$表示串$i$的后缀和串$j$的前缀的最长匹配长度. $f_{s, i} ...
- c语言中会遇到的面试题
预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 ...
- Oracle中的学习笔记
1.使用 ||来连接字符串 select CARD_ID ||','||CARD_TYPE as qqq from CARDS t 2.DISTINCT (唯一不重复) select DISTINCT ...
- 第一个HelloWorld!
$.介绍 1.eclipse的基本使用 2.第一个程序HelloWorld 3.总结 $.基本使用 对于刚入门的java新手来说选择一个舒适的编译器能让你快速的上手java的程序编写. 针对英语low ...
- 清理前一天log日志shell
清理前一天log日志shell #!/bin/bashlogPathList=`cat <<STD/data/logs/aiclass/backcms/data/logs/aiclass/ ...
- java基础之语法和开发规则
一. 代码书写的规则 以下面为例: 先写好结构 注意:为了避免错误,写代码时先把括号打齐,然后再补内容,每个”{}”里的内容开始写时要相比上一行多8个空格.为了方便可以用键盘上的 键代替(一般情况下时 ...
- 洛谷 P3586 [POI2015]LOG
P3586 [POI2015]LOG 题目描述 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这个序列上,每次选出c个正数,并将它 ...
- ADX3000 三层网络 纠错
基于三层网络设计要点: 1 组网配置,两端LAN口,IP地址不同网段,设置主IP地址,当做网段内部的网关使用 2 接口域添加trust接口 3 静态IP,有且仅能有一条,目的IP 0.0.0.0 子网 ...
- 字符串格式化str.format
一.字符串格式化之str.format 1.位置参数:用{0},{1},{2}表示位置 v1 = '{1},{0},{1}'.format('a','b') #输出b,a,b 2.关键词参数:用{na ...
- CF1117G Recursive Queries
题意:给定一个序列,定义[l, r]的最大值在m处,求f(l, r) = f(l, m - 1) + (r - l + 1) + f(m + 1, r).多次询问.100w. 解:考虑这个区间内每个数 ...