Linux系统编程——进程间通信:共享内存
概述
url=MdyPihmS_tWLwgWL5CMzaTrwDFHu6euAJJUAjKvlzbJmRw7RfhmkBWwAloo7Y65hLY-kQdHsbqWYP2wc2fk8yq">共享内存
当一个进程改变了这块地址中的内容的时候,其他进程都会察觉到这个更改。
共享内存的特点:
1)共享内存是进程间共享数据的一种最快的方法。
一个进程向共享的内存区域写入了数据,共享这个内存区域的全部进程就能够立马看到当中的内容。
2)使用共享内存要注意的是多个进程之间对一个给定存储区訪问的相互排斥。
若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。
经常使用函数
1)创建共享内存
所需头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size,int shmflg);
功能:
创建或打开一块共享内存区。
參数:
key:进程间通信键值。ftok() 的返回值。
size:该共享存储段的长度(字节)。
shmflg:标识函数的行为及共享内存的权限。其取值例如以下:
IPC_CREAT:假设不存在就创建
IPC_EXCL: 假设已经存在则返回失败
位或权限位:共享内存位或权限位后能够设置共享内存的訪问权限,格式和 open() 函数的 mode_t 一样(open() 的使用请点此链接),但可运行权限未使用。
返回值:
成功:共享内存标识符。
失败:-1。
演示样例代码例如以下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h> #define BUFSZ 1024 int main(int argc, char *argv[])
{
int shmid;
key_t key; key = ftok("./", 2015);
if(key == -1)
{
perror("ftok");
} //创建共享内存
shmid = shmget(key, BUFSZ, IPC_CREAT|0666);
if(shmid < 0)
{
perror("shmget");
exit(-1);
} return 0;
}
执行结果例如以下:
2)共享内存映射
所需头文件:
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
将一个共享内存段映射到调用进程的数据段中。简单来理解,让进程和共享内存建立一种联系,让进程某个指针指向此共享内存。
參数:
shmid:共享内存标识符。shmget() 的返回值。
shmaddr:共享内存映射地址(若为 NULL 则由系统自己主动指定)。推荐使用 NULL。
shmflg:共享内存段的訪问权限和映射条件( 通常为 0 ),详细取值例如以下:
0:共享内存具有可读可写权限。
SHM_RDONLY:仅仅读。
SHM_RND:(shmaddr 非空时才有效)
返回值:
成功:共享内存段映射地址( 相当于这个指针就指向此共享内存 )
失败:-1
3)解除共享内存映射
所需头文件:
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
功能:
将共享内存和当前进程分离( 不过断开联系并不删除共享内存。相当于让之前的指向此共享内存的指针,不再指向)。
參数:
shmaddr:共享内存映射地址。
返回值:
成功:0
失败:-1
4)共享内存控制
所需的头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
共享内存属性的控制。
參数:
shmid:共享内存标识符。
cmd:函数功能的控制,其取值例如以下:
IPC_RMID:删除。(经常使用
)
IPC_SET:设置 shmid_ds 參数,相当于把共享内存原来的属性值替换为 buf 里的属性值。
IPC_STAT:保存 shmid_ds 參数,把共享内存原来的属性值备份到 buf 里。
SHM_LOCK:锁定共享内存段( 超级用户 )。SHM_UNLOCK:解锁共享内存段。
SHM_LOCK 用于锁定内存,禁止内存交换。
并不代表共享内存被锁定后禁止其他进程訪问。其真正的意义是:被锁定的内存不同意被交换到虚拟内存中。这样做的优势在于让共享内存一直处于内存中,从而提高程序性能。
buf:shmid_ds 数据类型的地址(详细类型请点此链接 ),用来存放或改动共享内存的属性。
返回值:
成功:0
失败:-1
实战演示样例
接下来我们做这么一个样例:创建两个进程,在 A 进程中创建一个共享内存,并向其写入数据。通过 B 进程从共享内存中读取数据。
写端代码例如以下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h> #define BUFSZ 512 int main(int argc, char *argv[])
{
int shmid;
int ret;
key_t key;
char *shmadd; //创建key值
key = ftok("../", 2015);
if(key == -1)
{
perror("ftok");
} //创建共享内存
shmid = shmget(key, BUFSZ, IPC_CREAT|0666);
if(shmid < 0)
{
perror("shmget");
exit(-1);
} //映射
shmadd = shmat(shmid, NULL, 0);
if(shmadd < 0)
{
perror("shmat");
_exit(-1);
} //拷贝数据至共享内存区
printf("copy data to shared-memory\n");
bzero(shmadd, BUFSZ); // 共享内存清空
strcpy(shmadd, "how are you, mike\n"); return 0;
}
读端代码例如以下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h> #define BUFSZ 512 int main(int argc, char *argv[])
{
int shmid;
int ret;
key_t key;
char *shmadd; //创建key值
key = ftok("../", 2015);
if(key == -1)
{
perror("ftok");
} system("ipcs -m"); //查看共享内存 //打开共享内存
shmid = shmget(key, BUFSZ, IPC_CREAT|0666);
if(shmid < 0)
{
perror("shmget");
exit(-1);
} //映射
shmadd = shmat(shmid, NULL, 0);
if(shmadd < 0)
{
perror("shmat");
exit(-1);
} //读共享内存区数据
printf("data = [%s]\n", shmadd); //分离共享内存和当前进程
ret = shmdt(shmadd);
if(ret < 0)
{
perror("shmdt");
exit(1);
}
else
{
printf("deleted shared-memory\n");
} //删除共享内存
shmctl(shmid, IPC_RMID, NULL); system("ipcs -m"); //查看共享内存 return 0;
}
执行结果例如以下:
Linux系统编程——进程间通信:共享内存的更多相关文章
- linux系统编程--进程间通信
IPC方法 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问, 要交换数据必须通过内核,在内核中开 ...
- Linux系统编程——进程间通信(System V IPC 对象)
基本查看命令 ipcs -m查看共享内存 ipcs -s查看信号量 ipcs -q查看消息队列 ipcrm -m id 删除共享内存 -M+key值 ipcrm ...
- Linux系统编程——进程间通信:信号中断处理
什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFb ...
- linux网络编程之共享内存介绍
今天是个好日子,洋人之节乃全球同庆,圣诞一来感觉就要过年了,不过今晚心情有点打折扣,给心爱的人打电话没有打通,本想在平安夜送上快乐的祝福给她,糟糕的心情让自己好像泄了气的皮球一样,无精打彩,心情灰暗, ...
- Linux环境编程之共享内存区(一):共享内存区简单介绍
共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...
- Linux系统编程——进程间通信(一)
基本操作命令: ps -ajx/-aux/-ef 查看进程间状态/的相互关系 top 动态显示系统中的进程 nice 按照指定的优先级运行 /renice 改变正在运行的进程的优先级 kill -9杀 ...
- Linux系统编程——进程间通信:管道(pipe)
管道的概述 管道也叫无名管道,它是是 UNIX 系统 IPC(进程间通信) 的最古老形式,全部的 UNIX 系统都支持这样的通信机制. 无名管道有例如以下特点: 1.半双工,数据在同一时刻仅仅能在一个 ...
- Linux系统编程——进程间通信:命名管道(FIFO)
命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...
- Linux下进程间通信--共享内存:最快的进程间通信方式
共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...
随机推荐
- VUE:过渡&动画
VUE:过渡&动画 vue动画的理解 1)操作css的 trasition 或 animation 2)vue会给目标元素添加/移除特定的class 3)过渡的相关类名 xxx-enter-a ...
- 【2018 Multi-University Training Contest 2 1007】Naive Operations
[链接] 我是链接,点我呀:) [题意] 给你两个数组a,b; b数组是1..n的一个排列. 现在给你两种操作: add l,r将a[l..r]都加上1 query l,r 询问$∑^r_l\frac ...
- 2015 Multi-University Training Contest 3 hdu 5318 The Goddess Of The Moon
The Goddess Of The Moon Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/ ...
- 洛谷 P1301 魔鬼之城
P1301 魔鬼之城 题目描述 在一个被分割为N*M个正方形房间的矩形魔鬼之城中,一个探险者必须遵循下列规则才能跳跃行动.他必须从(1, 1)进入,从(N, M)走出:在每一房间的墙壁上都写了一个魔法 ...
- Linux 网络搭建
如果系统环境崩溃. 调用/usr/bin/vim /etc/profile Windows 1 本地连接使用固定IP vmware 8 2 修改Windows的hosts地址 ...
- POJ 1306
其实求的这个数的式子化简一下,就是C(N,M)..... #include <iostream> #include <algorithm> #include <cstdi ...
- MongoDB基本概念和安装配置
基本概念 MongoDB直接存储JSON. 有了NoSQL数据库之后,可以直接在业务层将数据按照指定的结构进行存储. NO SQL NoSQL 1 数据库 数据库 2 表 集合 3 行 文档 4 列 ...
- 相辅相成的求最单源短路径算法:(SPFA& dijkstra)
引用一位老oier的话: 一道题如果边权没有负数,那么一定是在卡SPFA.这时候就用到了堆优化的Dijkstra; 写在前面: 多打代码! 最好都掌握,灵活变通 SPFA: 主要用于稀疏图和有负权边的 ...
- mysql实战45讲 (三) 事务隔离:为什么你改了我还看不见 极客时间读书笔记
提到事务,你肯定不陌生,和数据库打交道的时候,我们总是会用到事务.最经典的例子就是转账,你要给朋友小王转100块钱,而此时你的银行卡只有100块钱. 转账过程具体到程序里会有一系列的操作,比如查询余额 ...
- iOS开发-Tools-CocoaPods
CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,AFNetWorking等等.可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而 ...