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

Posted 蚍蜉撼树谈何易

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

在这里插入图片描述

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

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任务产生的数据。强调的是多任务间按顺序运行

互斥

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

以上是关于Linux系统编程 --进程间通信 -共享内存的主要内容,如果未能解决你的问题,请参考以下文章

(46)LINUX应用编程和网络编程之一Linux应用编程框架

Linux系统下C语言的编程技巧

linux层面算编程吗

Linux 系统编程 -进程概念篇

linux文件编程----系统调用

Linux C/C++ 零基础学习编程教程,Linux 系统编程教程