学习笔记: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 ...
随机推荐
- ORA-00001:unique constraint violated解决
转自:https://www.2cto.com/database/201211/172340.html ORA-00001:unique constraint violated解决 今天往数据库中插入 ...
- Python中的上下文管理器(contextlib模块)
上下文管理器的任务是:代码块执行前准备,代码块执行后收拾 1 如何使用上下文管理器: 打开一个文件,并写入"hello world" filename="my.txt&q ...
- CentOS7安装CDH 第十四章:CDH的优化
相关文章链接 CentOS7安装CDH 第一章:CentOS7系统安装 CentOS7安装CDH 第二章:CentOS7各个软件安装和启动 CentOS7安装CDH 第三章:CDH中的问题和解决方法 ...
- DNS服务——搭建企业内网DNS服务器的作用
前言 DNS服务——服务端 和 客户端 配置 介绍了如何在DNS安装DNS服务,更改一下配置文件就可以依据根提示解析全球域名.既然使用互联网上的DNS服务器就可以解析全球域名,为何还要自掏腰包搭建DN ...
- HTML&CSS基础-ps的基本操作
HTML&CSS基础-ps的基本操作 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们工作中可能会经常需要将一个图片做成一个网页,而图片中的字体大小,行间距,图中lo ...
- apache配置https加密传输
环境:两台linux虚拟机和一台windows本机,一台充当要使用https传输的web服务器apache2.4.4,另一台CA服务器,window测试https配置. 1.CA服务器生成私有CA 1 ...
- python函数名的应用、闭包和迭代器
一.函数名的应用(第一类对象) 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数变量. 1.函数名的内存地址 def func(): print("哈哈") prin ...
- 高性能集群(HPC
串行计算与并行计算1.串行计算串行计算是指在单个计算机(拥有单个中央独立单元) 上执行软件写操作.CPU 逐个使用一系列指令解决问题.为了加快处理速度,在原有的串行计算的基础上演变出并行计算2.并行计 ...
- @EnableCircuitBreaker熔断超时机制
客户端请求服务端的时候总是报超时,默认熔断机制是1S
- Jfinal undertow本地运行加载静态文件
undertow部署文档中可配置静态资源也可以添加磁盘目录作为项目中得静态文件访问 undertow.resourcePath = src/main/webapp, D:/static 这样配置就可以 ...