当前位置: 首页 > 编程日记 > 正文

进程间通信IPC之--共享内存

每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲 区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)

如下图所示:
进程间通信共七种方式:
第一类:传统的unix通信机制:

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
第二类:System V IPC: 
# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

第三类:BSD 套接字:
# 套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
本文介绍IPC之共享内存:
共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。进程可以直接读取共享内存,不需要拷贝数据。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
步骤:
共享内存的使用,主要有以下几个API:ftok()、shmget()、shmat()、shmdt()及shmctl()
①创建/打开共享内存
int shmget(key_t key,int size,int shmflag);
例:
key = ftok(".", 'm');
shmid = shmget(key,1024,0666|IPC_CREAT|IPC_EXCL);
参数说明:
key:是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了。
产生key的方法:key_t ftok(const char *pathname, int proj_id);
1)pathname一定要在系统中存在并且进程能够访问的
2)proj_id是一个1-255之间的一个整数值,典型的值是一个ASCII值。如'a',考虑到应用系统可能在不同的主机上应用,可以直接定义一个key,而不用ftok获得:

#define IPCKEY 0x344378

size:申请内存的大小
shmflag:  这块内存的模式(mode)以及权限标识(0666等)。
 模式可取如下值:        
IPC_CREAT 新建(如果已创建则返回目前共享内存的id)
IPC_EXCL   与IPC_CREAT结合使用,如果已创建则则返回错误 
 其他模式略
申请的内存里面为空,即全为0
②映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
void *shmat( int shmid , char *shmaddr , int shmflag );
例:
void *p;
p=shmat(shmid,NULL,0);
参数说明:
shmid:是那块共享内存的ID。
shmaddr:共享内存映射的起始地址,一般不指定即NULL
shmflag:本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。0是读写模式
返回值: 成功时,这个函数返回共享内存的起始地址。失败时返回-1。
③撤销共享内存映射,删除本进程对这块内存的使用
int shmdt(const void* shmaddr);
例:
shmdt(p);
参数说明:
shmaddr:共享内存的起始地址。
返回值:成功时返回0。失败时返回-1。
④删除共享内存对象
int shmctl( int shmid , int cmd , struct shmid_ds *buf );
例:
shmctl(shmid, IPC_RMID, NULL);(删除共享内存)
参数说明:
shmid:共享内存的ID。
cmd:控制命令,可取值如下:
        IPC_STAT        得到共享内存的状态
        IPC_SET         改变共享内存的状态
        IPC_RMID        删除共享内存
buf:一个结构体指针。用以保存/设置属性。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。
返回值:成功时返回0。失败时返回-1。
无代码无真相
功能说明:两个进程通过共享内存一个写一个读并打印数据
  1. /*name:writer.c
  2. *function:写端进程向共享内存写数据
  3. * */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/ipc.h>
  12. #include <sys/shm.h>
  13. #define N 64
  14. typedef struct
  15. {
  16. pid_t pid;
  17. char buf[N];
  18. } SHM;
  19. void handler(int signo)
  20. {
  21. //printf("get signal\n");
  22. return;
  23. }
  24. int main()
  25. {
  26. key_t key;
  27. int shmid;
  28. SHM *p;
  29. pid_t pid;
  30. if ((key = ftok(".", 'm')) < 0)
  31. {
  32. perror("fail to ftok");
  33. exit(-1);
  34. }
  35. signal(SIGUSR1, handler);//注册一个信号处理函数
  36. if ((shmid = shmget(key, sizeof(SHM), 0666|IPC_CREAT|IPC_EXCL)) < 0)
  37. {
  38. if (EEXIST == errno)//存在则直接打开
  39. {
  40. shmid = shmget(key, sizeof(SHM), 0666);
  41. p = (SHM *)shmat(shmid, NULL, 0);
  42. pid = p->pid;
  43. p->pid = getpid();
  44. kill(pid, SIGUSR1);
  45. }
  46. else//出错
  47. {
  48. perror("fail to shmget");
  49. exit(-1);
  50. }
  51. }
  52. else//成功
  53. {
  54. p = (SHM *)shmat(shmid, NULL, 0);
  55. p->pid = getpid();//把自己的pid写到共享内存
  56. pause();
  57. pid = p->pid;//得到读端进程的pid
  58. }
  59. while ( 1 )
  60. {
  61. printf("write to shm : ");
  62. fgets(p->buf, N, stdin);//接收输入
  63. kill(pid, SIGUSR1);//向读进程发SIGUSR1信号
  64. if (strcmp(p->buf, "quit\n") == 0) break;
  65. pause();//阻塞,等待信号
  66. }
  67. shmdt(p);
  68. shmctl(shmid, IPC_RMID, NULL);//删除共享内存
  69. return 0;
  70. }
  1. /*name:reader.c
  2. *function:读端进程从共享内存中读数据
  3. * */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/ipc.h>
  12. #include <sys/shm.h>
  13. #define N 64
  14. typedef struct
  15. {
  16. pid_t pid;
  17. char buf[N];
  18. } SHM;
  19. void handler(int signo)
  20. {
  21. //printf("get signal\n");
  22. return;
  23. }
  24. int main()
  25. {
  26. key_t key;
  27. int shmid;
  28. SHM *p;
  29. pid_t pid;
  30. if ((key = ftok(".", 'm')) < 0)
  31. {
  32. perror("fail to ftok");
  33. exit(-1);
  34. }
  35. signal(SIGUSR1, handler);//注册一个信号处理函数
  36. if ((shmid = shmget(key, sizeof(SHM), 0666|IPC_CREAT|IPC_EXCL)) < 0)
  37. {
  38. if (EEXIST == errno)//存在则直接打开
  39. {
  40. shmid = shmget(key, sizeof(SHM), 0666);
  41. p = (SHM *)shmat(shmid, NULL, 0);
  42. pid = p->pid;
  43. p->pid = getpid();//把自己的pid写到共享内存
  44. kill(pid, SIGUSR1);
  45. }
  46. else//出错
  47. {
  48. perror("fail to shmget");
  49. exit(-1);
  50. }
  51. }
  52. else//成功
  53. {
  54. p = (SHM *)shmat(shmid, NULL, 0);
  55. p->pid = getpid();
  56. pause();
  57. pid = p->pid;//得到写端进程的pid
  58. }
  59. while ( 1 )
  60. {
  61. pause();//阻塞,等待信号
  62. if (strcmp(p->buf, "quit\n") == 0) exit(0);//输入"quit结束"
  63. printf("read from shm : %s", p->buf);
  64. kill(pid, SIGUSR1);//向写进程发SIGUSR1信号
  65. }
  66. return 0;
  67. }

相关文章:

Scons构建C++项目

旧博文&#xff0c;搬到 csdn 原文&#xff1a;http://rebootcat.com/2020/08/30/scons/ 前言 我是一个 linux c 开发者&#xff0c;但是一直对 Makefile 的语法很是头痛&#xff0c;每次都记不住&#xff0c;所以每次写 Makefile 都很痛苦&#xff0c;Makefile 里需要你自己编…

2020 AI产业图谱启动,勾勒中国AI技术与行业生态

《2020年国务院政府工作报告》提出&#xff0c;重点支持「两新一重」建设。其中「两新一重」中的第一个「新」&#xff0c;就是新基建&#xff0c;而人工智能是新基建的重要组成部分。新基建首次被纳入政府工作报告后&#xff0c;各大科技厂商纷纷押注&#xff0c;重金投向「新…

Windows Phone 7 SDK 7.1 Beta2 发布

早上看到消息&#xff0c;有Marketplace账号的筒子们注意了&#xff0c;可以去下载芒果的ROM了&#xff0c;一个开发者账号只能更新一个WP7&#xff0c;以下是App hub上的消息&#xff1a;来自http://create.msdn.com/en-US/news/Mango_Beta。关于开发工具的更新&#xff0c;可…

javascript基础语法——表达式

前面的话 一般地&#xff0c;关于javascript基础语法&#xff0c;人们听得比较多的术语是操作符和语句。但是&#xff0c;其实还有一个术语经常使用&#xff0c;却很少被提到&#xff0c;这就是javascript表达式(expression)。本文将详细介绍javascript表达式&#xff0c;表达式…

Hexo Next 博客添加相册瀑布流

原文&#xff1a;https://rebootcat.com/2020/09/19/nextphotowall/ 前言 一直没有时间来整理下博客搭建的一些事情&#xff0c;现在补上一篇&#xff0c;给 Hexo Next 博客添加一个相册功能&#xff0c;使用瀑布流的方式。 原理说明 使用 github 作为仓库存储图片文件&…

【分享几个日常巡检 监控数据库的语句】

查看数据库表空间语句 select df.tablespace_name "表空间名",totalspace "总空间M",freespace "剩余空间M",round((1-freespace/totalspace)*100,2) "使用率%" from (select tablespace_name,round(sum(bytes)/1024/1024) totalspa…

AI换脸、声音篡改等,明确写入新版《民法典》

来源 | HyperAI超神经5 月 28 日&#xff0c;十三届全国人大三次会议表决通过了《中华人民共和国民法典》&#xff08;以下简称《民法典》&#xff09;第四编人格权中的第四章肖像权&#xff0c;明确提出了以信息技术手段&#xff0c;对于他人肖像、声音等权益的侵害认定。《民…

awk: (FILENAME=- FNR=1) 致命错误: 试图访问字段 -2

执行&#xff1a;awk {print $(NF-2)} aa.log出现错误&#xff1a;awk: (FILENAMEaa.log FNR1) 致命错误: 试图访问字段 -2可能和aa.log中数据有关系&#xff1a;改为&#xff1a;awk NF>1{print $(NF-2)} aa.log转载于:https://blog.51cto.com/henly/1786692

迁移博客到香港虚拟空间

原文&#xff1a; https://rebootcat.com/2020/09/20/virtual_space_blog/ 缘起 我的博客一直采用的是 github pages 来托管&#xff0c;中间断断续续的也没怎么管理过&#xff0c;偶尔写几篇博客&#xff0c;所以也就没怎么关心过访问速度&#xff0c;搜索引擎收录等问题。 …

自动化神经网络理论进展缓慢,AutoML算法的边界到底在哪?

作者 | 夕颜出品 | CSDN&#xff08;ID:CSDNnews&#xff09;「AI 技术生态论」 人物访谈栏目是 CSDN 发起的百万人学 AI 倡议下的重要组成部分。通过对 AI 生态顶级大咖、创业者、行业 KOL 的访谈&#xff0c;反映其对于行业的思考、未来趋势判断、技术实践&#xff0c;以及成…

让电脑通过gns3里的路由器上网

题目我感觉写的不好&#xff0c;反正就是这个意思&#xff0c;看下文 头几天有网友问cisco2811路由器怎么用ACL封掉QQ&#xff0c;当时就想帮他&#xff0c;但是手里又没有cisco路由器&#xff0c;只有GNS3 cisco模拟器。 现在的问题就是要用gns3模拟器的路由器充当真实工作中的…

文件上传的渐进式增强

文件上传是最古老的互联网操作之一。 20多年了&#xff0c;它几乎没变&#xff0c;还是原来的样子&#xff1a;操作麻烦、缺乏交互、用户体验不佳。在这个新技术日新月异的时代&#xff0c;显得非常落伍。 网页开发者们想了很多办法&#xff0c;试图提升文件上传的功能和操作体…

使用 mkdocs 搭建个人 wiki 站点

原文&#xff1a; https://rebootcat.com/2020/09/20/wiki/ why wiki 博客通常是用来记录一些完整的文章&#xff0c;每篇文章有一个主题。但是我想把平日里的一些笔记也记录到我的博客里&#xff0c;但笔记是零散的&#xff0c;随时的&#xff0c;不是完整的一个主题。所以打…

追忆童年,教你用Python画出儿时卡通人物

作者 | 张同学来源 | 凹凸数据大家好&#xff0c;我是张同学。又到一年一度的国际儿童节&#xff0c;作为逢节必过的程序猿&#xff0c;怎么可以放过这个学习技能的机会呢&#xff1f;于是&#xff0c;今天我们来学习 Python 的 Turtle 库绘制童年的卡通人物&#xff0c;一起做…

xx学OD -- 消息断点 RUN跟踪(上)

这一篇讲的是 消息断点和RUN跟踪的简单知识这一篇没怎么看明白 大概使用知道了 怎么用不太清楚。介绍本次软件特点输入后木有反应(纱布垃圾的。。哈哈)启动OllyDBG载入这个程序&#xff0c;F9让它运行。这个程序按我们前面讲的采用字串参考或函数参考的方法都很容易断下来。…

iOS-UIWebView添加头部和尾部

2019独角兽企业重金招聘Python工程师标准>>> 前言 项目中使用UIWebView显示本地或者是服务器上的页面很容易&#xff0c;但是仅限于显示页面&#xff0c;可控性并不高&#xff0c;如果有需要在头部和尾部加上原生的view&#xff0c;显示部分信息相对于全部使用UIWeb…

epoll 入门例子 tcp server/client

原文&#xff1a; https://rebootcat.com/2020/09/26/epoll_examples/ 复习一下 上一篇博文 epoll原理深入分析 详细分析了 epoll 底层的实现原理&#xff0c;如果对 epoll 原理有模糊的建议先看一下这篇文章。那么本文就开始用 epoll 实现一个简单的 tcp server/client。 本…

张红忠:智慧化时代,如何通吃5G模组、AIoT?

受访者 | 张红忠&#xff0c;日海智能副总裁、云AIoT创新中心总经理记者 | Aholiab&#xff0c;编辑 | 邓晓娟出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;日海智能是目前国内AIoT领域的头部企业&#xff0c;以AIoT为核心&#xff0c;形成了5G&AI物联网终端、…

JQUERY打造隐藏在左侧的弹性弹出菜单

代码简介&#xff1a; 隐藏在左侧的弹性弹出菜单&#xff0c;从淘宝扣下来的&#xff0c;也可作为JAvaScript缓冲动画的典型教程。本弹性菜单可扩展性强&#xff0c;实际上不光可以做成菜单&#xff0c;也可布局一些图文混排的内容或一段视频&#xff0c;总之被弹出的内容是在一…

Num55 boss09(activiti安装以及API)

2019独角兽企业重金招聘Python工程师标准>>> 安装流程设计器插件&#xff1a; 使用框架提供的方式创建23张表&#xff1a; 流程部署&#xff0c;定义&#xff0c;启动&查询&#xff0c;办理任务&#xff1a; 流程的部署&#xff0c;查询&#xff0c;删除 & …

模仿nginx修改进程名

个人博客原文&#xff1a; https://rebootcat.com/2020/10/25/setproctitle/ nginx 进程名 使用 nginx 的过程中&#xff0c;我们经常看到 nginx 的进程名是不同的&#xff0c;如下&#xff1a; $ ps -ef |grep nginx smaug 1183 1115 0 05:46 pts/2 00:00:00 grep …

机器学习模型的超参数优化 | 原力计划

作者 | deephub责编 | 王晓曼出品 | CSDN博客头图 | CSDN付费下载自东方IC引言模型优化是机器学习算法实现中最困难的挑战之一。机器学习和深度学习理论的所有分支都致力于模型的优化。机器学习中的超参数优化旨在寻找使得机器学习算法在验证数据集上表现性能最佳的超参数。超参…

准备IE--复习NP,NP从头开始,每天学一点,就多一点收获

2011-07-07 今天开始重新开始NP&#xff01;每天一实验&#xff0c;加油&#xff01;写下心路历程&#xff0c;为自己加油&#xff01;转载于:https://blog.51cto.com/sunchangsheng/605482

[20160608]自治事务引起死锁.txt

[20160608]自治事务引起死锁.txt --链接http://www.itpub.net/thread-2060966-2-1.html上的讨论,很久以前也遇到过 --(http://blog.itpub.net/267265/viewspace-721262/),时间有点久远,自己重复测试看看: 1.环境: SCOTTtest> &r/ver1 PORT_STRING V…

动感效果的TAB选项卡 jquery 插件

动感效果的TAB选项卡 jquery 插件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head><me…

Linux上隐藏进程名(初级版)

缘起 上一篇博文 模仿nginx修改进程名 中提到了一种修改进程名的方法&#xff0c;就像 nginx 一样&#xff0c;给不同进程命名为 master 以及 worker 等。那么能不能把新进程名设置为空字符串呢&#xff1f;如果能&#xff0c;又会有哪些应用场景呢&#xff1f; 答案可能是能…

神操作!一行Python代码搞定一款游戏?给力!

来源&#xff1a;pypl编程榜一直以来Python长期霸占编程语言排行榜前三位&#xff0c;其简洁&#xff0c;功能强大的特性使越来越多的小伙伴开始学习Python 。甚至K12的同学都开始学习Python 编程。新手入门的时候趣味性其实最重要的。那么一行Python 代码到底能玩出什么花样&a…

jquery对所有input type=text的控件赋值

function resetData() { $("input[typetext]").each( function() { $(this).attr("value",""); } ); }

free not return memory

个人博客&#xff1a;https://rebootcat.com/2020/11/05/free_mem/ 内存泄露&#xff1f; 观察到一台机器上的内存使用量在程序启动之后&#xff0c;持续增长&#xff0c;中间没有出现内存恢复。怀疑是不是出现了内存泄露的问题&#xff1f; 然后使用相关的内存分析工具进行了…

成大事必备9种能力

挑战生存的能力&#xff1a;善于在现实中寻找答案 1、摆正心态&#xff0c;敢于面对现实 对于那些不停地抱怨现实恶劣的人来说&#xff0c;不能称心如意的现实&#xff0c;就如同生活的牢笼&a…