Linux系统编程 --进程间通信 -共享内存

共享内存概念

共享内存区是最快的IPC(进程间通信)形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
与管道区别:
1.管道的本质是一个文件,其进程间通信依赖I/O进行操作。而共享内存本质是多个进程共享一份内存,通过读写端不同来达到进程通信的目的。
2.管道在创建默认情况下读端为阻塞模式,而共享内存不会这样。

共享内存的本质。

在这里插入图片描述
在这里插入图片描述

共享内存的描述与组织

共享内存的描述

在这里插入图片描述

共享内存的组织

在这里插入图片描述

共享内存的分配原则

以页为基本单位,假设这个页的大小为4k的话,此时你非要去申请4097字节的话,它会给你两页,但是你只能使用4097字节。

共享内存的相关函数

在这里插入图片描述

获取key值

因为首先要生成一个唯一的key值,所以必须调用ftok()这个函数
在这里插入图片描述

 1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include"mp.h"
  5 using namespace std;
  6 int main()
  7 {
  8     key_t key=ftok(PATH,proj_id);                                                                                                                                                     
  9     cout<<key<<endl;
 10     return 0;
 11 }

在这里插入图片描述

获取共享内存

在这里插入图片描述

  1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include<sys/shm.h>
  5 #include"mp.h"
  6 using namespace std;
  7 int main()
  8 {
  9     key_t key=ftok(PATH,proj_id);
 10     int shmid=shmget(key,4096,IPC_CREAT|IPC_EXCL);
 11     if(shmid<0)
 12     {
 13         cerr<<"shmget()"<<endl;
 14         return 1;
 15     }
 16     hex(cout);
 17     cout<<"my key is "<<key<<endl;
 18     dec(cout);                                                                                                                                                                        
 19     cout<<"my shmid is "<<shmid<<endl;
 20     return 0;
 21 }

在这里插入图片描述
介绍两个命令: ipcs -m 查看共享内存
在这里插入图片描述
删除共享内存的命令 ipcrm -m + 共享内存的shmid号
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
上图的perms的值为0,表明我没有任何权限,那要这个共享内存干嘛?所以我们在创建时必须给其加上权限。以八进制方式加

 1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include<sys/shm.h>
  5 #include"mp.h"
  6 using namespace std;
  7 int main()
  8 {
  9     key_t key=ftok(PATH,proj_id);
 10     int shmid=shmget(key,4096,IPC_CREAT|IPC_EXCL|0664);                                                                                                                               
 11     if(shmid<0)
 12     {
 13         cerr<<"shmget()"<<endl;
 14         return 1;
 15     }
 16     hex(cout);
 17     cout<<"my key is "<<key<<endl;
 18     dec(cout);
 19     cout<<"my shmid is "<<shmid<<endl;
 20     return 0;
 21 }
~

在这里插入图片描述

删除共享内存

在这里插入图片描述

我们可以使用ipcrm -m +shmid 命令删除,但共享内存为什么不能用完不用我们自己手动去释放,而是调用一个函数去释放它,这里介绍。

在这里插入图片描述
在这里插入图片描述

 1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include<unistd.h>                                                                                                                                                                    
  5 #include<sys/shm.h>
  6 #include"mp.h"
  7 using namespace std;
  8 int main()
  9 {
 10     key_t key=ftok(PATH,proj_id);
 11     int shmid=shmget(key,4096,IPC_CREAT|IPC_EXCL|0664);
 12     if(shmid<0)
 13     {
 14         cerr<<"shmget()"<<endl;
 15         return 1;
 16     }
 17     hex(cout);
 18     cout<<"my key is "<<key<<endl;
 19     dec(cout);
 20     cout<<"my shmid is "<<shmid<<endl;
 21     sleep(10);
 22     shmctl(shmid,IPC_RMID,NULL);
 23     return 0;
 24 }

在这里插入图片描述

共享内存的挂载

在这里插入图片描述

在这里插入图片描述

    1 #include<iostream>
    2 #include<sys/ipc.h>
    3 #include<sys/types.h>
    4 #include<unistd.h>
    5 #include<sys/shm.h>
    6 #include"mp.h"
    7 using namespace std;
    8 int main()
    9 {
   10     key_t key=ftok(PATH,proj_id);
   11     int shmid=shmget(key,4096,IPC_CREAT|IPC_EXCL|0664);
   12     if(shmid<0)
   13     {
   14         cerr<<"shmget()"<<endl;
   15         return 1;
   16     }
   17     hex(cout);
   18     cout<<"my key is "<<key<<endl;
   19     dec(cout);
   20     cout<<"my shmid is "<<shmid<<endl;
W> 21    char* s=(char*)shmat(shmid,NULL,0);
   22    sleep(10);                                                                        
   23     shmctl(shmid,IPC_RMID,NULL);
   24     return 0;
   25 }

在这里插入图片描述

去除挂载

在这里插入图片描述

*int shmdt(const void shmaddr); 只需要将shmat返回值传入即可

  1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include<unistd.h>
  5 #include<sys/shm.h>
  6 #include"mp.h"
  7 using namespace std;
  8 int main()
  9 {
 10     key_t key=ftok(PATH,proj_id);
 11     int shmid=shmget(key,4096,IPC_CREAT|IPC_EXCL|0664);
 12     if(shmid<0)
 13     {
 14         cerr<<"shmget()"<<endl;
 15         return 1;
 16     }
 17     hex(cout);
 18     cout<<"my key is "<<key<<endl;
 19     dec(cout);
 20     cout<<"my shmid is "<<shmid<<endl;
 21    char* s=(char*)shmat(shmid,NULL,0);
 22    sleep(10);
 23    shmdt(s);
 24    sleep(4);                                                                           
 25     shmctl(shmid,IPC_RMID,NULL);
 26     return 0;
 27 }

在这里插入图片描述

利用共享内存实现简单通信

mp.h

   #pragma  once
  2 #define PATH "/tmp"                                                                                                                                                                   
  3 #define proj_id 7756

server

  1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include<unistd.h>
  5 #include<sys/shm.h>
  6 #include"mp.h"
  7 using namespace std;
  8 int main()
  9 {
 10     key_t key=ftok(PATH,proj_id);
 11     int shmid=shmget(key,4096,IPC_CREAT|IPC_EXCL|0664);
 12     if(shmid<0)
 13     {
 14         cerr<<"shmget()"<<endl;
 15         return 1;
 16     }
 17     hex(cout);
 18     cout<<"my key is "<<key<<endl;
 19     dec(cout);
 20     cout<<"my shmid is "<<shmid<<endl;
 21    char* s=(char*)shmat(shmid,NULL,0);
 22    while(1)
 23    {
 24        sleep(1);
 25        cout<<s<<endl;                                                                  
 26    }
 27    shmdt(s);
 28     shmctl(shmid,IPC_RMID,NULL);
 29     return 0;
 30 }

client

  1 #include<iostream>
  2 #include<sys/ipc.h>
  3 #include<sys/types.h>
  4 #include<unistd.h>
  5 #include<sys/shm.h>
  6 #include"mp.h"
  7 using namespace std;
  8 int main()
  9 {
 10     key_t key=ftok(PATH,proj_id);
 11     int shmid=shmget(key,4096,0);
 12     if(shmid<0)
 13     {
 14         cerr<<"shmget()"<<endl;
 15         return 1;
 16     }
 17    char* s=(char*)shmat(shmid,NULL,0);
 18    char c='a';
 19    for(;c<='z';c++)
 20    {
 21        s[c-'a']=c;
 22        sleep(3);                                                                       
 23    }
 24     shmdt(s);
 25     return 0;
 26 }
~

在这里插入图片描述
共享内存底层不存在同步与互斥机制,因为在写的时候也可以读。

IPC命令

在这里插入图片描述

system V消息队列

消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
特性方面
IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核。

同步与互斥

临界区

在这里插入图片描述

同步

同步:是指散步在不同任务之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务,最基本的场景就是任务之间的依赖,比如A任务的运行依赖于B任务产生的数据。强调的是多任务间按顺序运行

互斥

互斥:是指散步在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行,最基本的场景就是对资源的同时写,为了保持资源的一致性,往往需要进行互斥访问。强调的是单个任务不可以被中止,该任务为原子性的,必须等它执行完后方可对该临界区访问。

  • 28
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值