学习笔记: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 ...
随机推荐
- stm32 SD卡
容量等级 SD容量有8MB.16MB.32MB.64MB.128MB.256MB.512MB.1GB.2GB SDHC容量有2GB .4GB.8GB.16GB.32GB SDXC容量有32GB.48G ...
- iOS10推送必看UNNotificationAttachment以及UNTimeIntervalNotificationTrigger
虽然这篇文章比较长,也不好理解,但是还是建议大家收藏,以后用到的时候,可以看看,有耐心的还是读一读. 这篇文章开始,我会跟大家好好讲讲,苹果新发布的iOS10的所有通知类. 一.创建本地通知事例详解: ...
- django 发帖时碰到的图片上传
所用编辑器 [wangEditor.js] 图片上传接口 '/edit/image/' 返回内容 参照 https://www.kancloud.cn/wangfupeng/wangeditor3/ ...
- HBase hbase-site.xml 参数
该文档是用hbase默认配置文件生成的,文件源是 hbase-default.xml. 在实际的HBase生产环境中应用于%HBASE_HOME%/conf/hbase-site.xml中. hbas ...
- kvm虚拟机在线调整硬件配置
#centos5.x版本不支持动态调整内存,CPU,以下是在centos6.x上测试 1.查看虚拟机信息 shell> virsh dumpxml cos_v1 | head -n 10 < ...
- Python_比较运算符
1.比较运算符
- Django REST framework+Vue 打造生鲜电商项目(笔记三)
(PS:转载自http://www.cnblogs.com/derek1184405959/p/8810591.html 有修改) 一.drf的过滤 (1)添加到app里面 INSTALLED_AP ...
- 进程与线程与GIL的总结
- C#经纬度加减运算(度°分′秒″格式)
经度是分和秒是按60进位,如果要做运算第一步就是转换成浮点数,之后就是计算和还原. using System.Text.RegularExpressions; public static double ...
- [Dart] Capture and Handle Data Sequences with Streams in Dart
Streams represent a sequence of asynchronous events. Each event is either a data event, also called ...