学习笔记:Linux下共享内存的方式实现进程间的相互通信
#一、常用函数
#函数系列头文件
```
#include
#include
#include
```
#ftok():
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
```
key_t ftok( char * fname, int id );//当成功执行的时候,一个key_t值将会被返回,否则 -1 被返回。
```
应用举例:
key_t key = ftok(".", 2);//通过ftok函数得到id值存在key中,下面创建共享内存时会用到
shmget() :
用于创建共享内存
int shmget(key_t key, size_t size, int shmflg); //成功返回共享内存的ID,出错返回-1
应用举例:
int shmid = shmget(key, 100, IPC_CREAT | IPC_EXCL | 0666);
//创建共享内存,成功返回共享内存的ID,出错返回-1,IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的共享内存,如果共享内存已存在,返回一个错误。
(1)第一个参数key是长整型(唯一非零),系统建立IPC通讯 ( 消息队列、 信号量和 共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到,由内核变成标识符,要想让两个进程看到同一个信号集,只需设置key值不变就可以。
(2)第二个参数size指定共享内存的大小,它的值一般为一页大小的整数倍(未到一页,操作系统向上对齐到一页,但是用户实际能使用只有自己所申请的大小)。
(3)第三个参数shmflg是一组标志,创建一个新的共享内存,将shmflg 设置了IPC_CREAT标志后,共享内存存在就打开。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的共享内存,如果共享内存已存在,返回一个错误。一般我们会还或上一个文件权限
shmctl():
用于操作共享内存
int shmctl(int shm_id, int cmd, struct shmid_ds *buf); //成功返回0,出错返回-1
(1)第一个参数,shm_id是shmget函数返回的共享内存标识符。
(2)第二个参数,cmd是要采取的操作,它可以取下面的三个值 :
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
(3)第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。 shmid_ds结构至少包括以下成员
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
shmat():
用于创建共享存储段之后,将进程连接到它的地址空间
void *shmat(int shm_id, const void *shm_addr, int shmflg); //成功返回指向共享存储段的指针,出错返回-1
应用举例:
void *pshm = shmat(shmid, 0, 0);//挂接操作,成功返回指向共享存储段的指针,出错返回-1
if (*(int *)pshm == -1) {//查看挂接是否成功如果出错返回-1,报错
printf("shmat error!\n");
exit(0);
}
(1)第一个参数,shm_id是由shmget函数返回的共享内存标识。
(2)第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
(3)第三个参数,shm_flg是一组标志位,通常为0
shmdt():
用于分离操作
int shmdt(const void *shmaddr); //成功返回0,出错返回-1
//addr参数是以前调用shmat时的返回值
二、函数实践
在设计实验中,运用共享内存的四个主要函数shmaget函数,shmat函数,shmdt函数,shmctl函数之后,读出传送数据的文件可以视为服务器read.c,传送数据相当于客户端文件write.c,实现进程之间的相互通信。
write.c程序段(将数据写入共享空间):
//write.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
struct Msg {
int flag;//0为读,1为写
char content[104];
};
int shmid;
void *pshm;
void Handle(int s) {//监听函数
if (s == 2)
{
shmdt(pshm);
shmctl(shmid, IPC_RMID, 0);
exit(0);
}
}
int main() {
signal(2, Handle);//按ctrl+c键退出时会处理这个消息,进行共享内存卸载、删除操作,最后exit(0)退出程序
key_t key = ftok(".", 2);//通过ftok函数得到id值存在key中
shmid = shmget(key, 100, IPC_CREAT | IPC_EXCL | 0666);/*创建共享内存,成功返回共享内存的ID,出错返回-1,IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的共享内存,如果共享内存已存在,返回一个错误。*/
pshm = shmat(shmid, 0, 0);//挂接操作,成功返回指向共享存储段的指针,出错返回-1
if (*(int *)pshm == -1) {//查看挂接是否成功如果出错返回-1,报错
printf("shmat error!\n");
exit(0);
}
memset(pshm, 0, 100);//初始化
struct Msg *msg = (struct Msg *)pshm;
msg->flag = 1;
while (1) {
if (msg->flag == 1) {//当为1时写消息,此时读文件中不能操作此共享内存
printf("请输入内容至共享内存:");
scanf("%s", msg->content);
msg->flag = 0;//当写消息后flag置为0,让读文件开始执行读操作,此时写文件不能进行写操作
}
else {
sleep(1);
}
}
return 0;
}
read.c程序段(将数据同步从共享空间读出):
//read.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
struct Msg {
int flag;
char content[104];
};
int main() {
key_t key = ftok(".", 2);
int shmid = shmget(key, 0, 0);//通过ftok函数得到id值存在key中
void *pshm = shmat(shmid, 0, 0);//挂接操作,成功返回指向共享存储段的指针,出错返回-1
if (*(int *)pshm == -1) {//查看挂接是否成功如果出错返回-1,报错
printf("shmat error!\n");
exit(0);
}
struct Msg * msg = (struct Msg *)pshm;
while (1) {
if (msg->flag == 0) {//当为0时读消息,此时写文件中不能操作此共享内存
printf("从共享内存收到 : %s\n", msg->content);
msg->flag = 1;
}
else {
sleep(1);
}
}
return 0;
}
运行结果与分析:

在程序运行中,同时打开两个终端,分别运行write和read程序,便能发现write将内容写入共享内存,而同时read进程自行同步将共享内存中的数据读出,进而实现进程通信 。
设计的这个实验的优点是方便简单,效率非常的高,有着很高的灵活性。但若有多个进程同时读取,可能会出现错误,解决该问题需要有一种进程同步的机制,或者借助其他手段来进行进程间的同步工作,将在接下来的学习中会进一步解决。
三、参考博客与资料
sky_Mata 的 进程间通信方式——共享内存: https://blog.csdn.net/skyroben/article/details/72625028
清清飞扬 的 linux ftok()函数: https://www.cnblogs.com/joeblackzqq/archive/2011/05/31/2065161.html
学习笔记:Linux下共享内存的方式实现进程间的相互通信的更多相关文章
- Windows中利用共享内存来实现不同进程间的通信
Windows中利用共享内存来实现不同进程间的通信 一.msdn详细介绍 https://docs.microsoft.com/zh-cn/windows/win32/memory/sharing-f ...
- 萌新笔记——linux下查看内存的使用情况
windows上有各种软件可以进行"一键加速"之类的操作,释放掉一些内存(虽然我暂时不知道是怎么办到的,有待后续学习).而任务管理器也可以很方便地查看各进程使用的内存情况,如下图: ...
- linux下共享内存mmap和DMA(直接访问内存)的使用 【转】
转自:http://blog.chinaunix.net/uid-7374279-id-4413316.html 介绍Linux内存管理和内存映射的奥秘.同时讲述设备驱动程序是如何使用“直接内存访问” ...
- linux 下共享内存
一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要 ...
- Linux 程序设计学习笔记----Linux下文件类型和属性管理
转载请注明出处:http://blog.csdn.net/suool/article/details/38318225 部分内容整理自网络,在此感谢各位大神. Linux文件类型和权限 数据表示 文件 ...
- MongoDB学习笔记—Linux下搭建MongoDB环境
1.MongoDB简单说明 a MongoDB是由C++语言编写的一个基于分布式文件存储的开源数据库系统,它的目的在于为WEB应用提供可扩展的高性能数据存储解决方案. b MongoDB是一个介于关系 ...
- python学习笔记——多进程中共享内存Value & Array
1 共享内存 基本特点: (1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝. (2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将 ...
- Java学习笔记——Linux下安装配置tomcat
朝辞白帝彩云间,千里江陵一日还. 两岸猿声啼不住,轻舟已过万重山. ——早发白帝城 首先需要安装配置JDK,这里简单回顾下.Linux下用root身份在/opt/文件夹下创建jvm文件夹,然后使用ta ...
- LINUX学习笔记——LINUX下EXP命令全库备份数据库文件
LINUX下EXP命令全库备份数据库文件 1)建立备份目录,目录操作权限授权给Oracle用户 mkdir /backup --创建backup文件夹 cd / --进入cd语句 ls -l ...
随机推荐
- 如何在SAP云平台ABAP编程环境里把CDS view暴露成OData服务
Jerry 2016年在学习SAP CDS view时,曾经写过一个CDS view的自学系列,其中有一篇提到了一个很方便的注解: @OData.publish: true 加上这个注解的CDS vi ...
- 使用SAP Cloud Platform Leonardo机器学习提取图片的特征向量
选中一个需要进行测试的Leonardo机器学习服务,点击Configure Environments: 因为我不想使用sandbox环境,所以我选择了eu10这个region: 维护clientid和 ...
- BKP和RTC
Stm32内部有多个BKP寄存器,在主电源被切断或者系统产生复位的时候,BKP寄存器仍然可以利用备用电源的支持保持其重要内容. BKP在实际应用中可以存入重要数据,防止被恶意查看. BKP有入侵检测, ...
- Cron 定时任务表达式
Cron Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth M ...
- nginx的gzip模块详解以及配置
文章来源 运维公会:nginx的gzip模块详解以及配置 1.gzip模块作用 gzip这个模块无论在测试环境还是生产环境都是必须要开启,这个模块能高效的将页面的内容,无论是html或者css.j ...
- unity图片保留周边,中间延伸
1.先把图片切割,类似下面这样的 2.然后在使用的时候(选择图片类型的时候选择sliced)
- 运维开发笔记整理-template的使用
运维开发笔记整理-Django的template的使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在上一篇博客中我们学习了HttpResponse 和JsonResponse方 ...
- Codeforces Round #512 (Div. 2) D. Vasya and Triangle(几何+思维)
题目 题意: 给出 n,m,k ,让你在长为 n,宽为 m 的坐标系里构建一个三角形,使得面积= n*m/k.如果存在,输出“YES”,输出三角形三个顶点的坐标: 如果不存在,输出“NO”. 思路: ...
- python访问aws-S3服务
创建本地 AWS 凭证文件 登录 AWS 管理控制台 并通过以下网址打开 IAM 控制台 https://console.amazonaws.cn/iam/. 创建一个新用户,其权限仅限于您希望您的代 ...
- 持续集成实践---基于ant+jmeter+jenkins接口CI
背景: 大纲: jmeter入门教程 jenkins入门教程 ant介绍 jmeter+ant脚本自动执行实践 接口测试CI实践