systemV的工作原理+原理代码

概念

我们知道进程间的通信有管道的方式进程通信管道制作_云的小站的博客-CSDN博客

但是我们的管道通信其实属于一种取巧的方式,利用了打开的文件可读写的特性上,两个进程对此分别进行读写操作就会产生所谓的通信现象,但是外面的管道依旧得再磁盘上创建一个文件,然后文件打开加载在内存上才可以使用,那么有什么方法可以直接加载在内存,而无需对磁盘操作呢?

---------利用systemV共享内存通信

利用系统函数shmget在内存中开辟一块空间用于进程通信的交互点。因为两个进程之间不可以直接通信,所以需要加一个中间层。

 systemV的工作原理+原理代码_第1张图片systemV的工作原理+原理代码_第2张图片

学计算机,当两个东西不通的时候,我们最经常干的事情就是加一个中间层,既保护了独立性,又处理了我们需要完成的事情

工具

shmget(创建共享内存)

shmid_t shmget(key_t key, size_t size, int shmflg);

 返回值:

失败返回-1,成功返回一个shmid唯一的共享内存标识符。

key:

唯一值,两个进程需要同一个key值才可以访问到同一共享内存空间。

size:

设置共享内存大小

shmflg

共享内存创建选项,IPC_CREAT | IPC_EXCL|0666 

IPC_CREAT:如果内存存在key标识符的共享内存直接使用,如果不存在就创建

IPC_EXCL:如果内存存在key标识符的共享内存直接失败退出。

0666:共享内存的使用权限。

shmctl(操作共享内存)

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

返回值:

如果操作成功返回0,操作失败返回-1;

shmid:

对该shmid的共享内存进行操作;

cmd:

对共享内存的操作选项,一般我们删除共享内存用的使用:IPC_RMID

buf:

获取该共享内存的数据结构地址。(共享内存也需要被描述组织)。

shmat(进程的挂接操作)

void *shmat(int shmid, const void *shmaddr, int shmflg);

返回值:

成功返回共享内存的地址,失败返回-1,并设置errno错误原因。

shmid:

挂接在shmid标识符的共享内存上。

shmaddr:

理论上可以自己设置将共享内存挂接在自己指定的位置,但是不建议。所以一般设置为nullptr,

shmflg

设置访问方式只读、只写等等。设置为0,读写操作。

shmdt(进程的拆除操作)

int shmdt(const void *shmaddr);

返回值:

成功拆除返回0,失败返回-1;

shmaddr:

将进程地址空间shmaddr的共享内存,进行拆除。

ftok(生成一个key值为shmget服务)

key_t ftok(const char *pathname, int proj_id);

返回值:

返回有个随机数字。

pathname:

传一个文件路径,使用文件的inode值,对了文件必须要有访问权限。

proj_id:

项目id,0~255,其实可以随便写,会截断。

ps:ftok不进行系统调用,他只是一个算法

代码

来来来,工具说完了直接上代码:

头文件

日志+需要的接口

日志

  1 #ifndef _LOG_H_
  2 #define _LOG_H_
  3 #include 
  4 #include 
  5 
  6 #define Debug 0
  7 #define Notice 1
  8 #define Warning 2
  9 #define Error 3
 10 
 11 std::string mgs[] = {
 12     "Debug",
 13     "Notice",
 14     "Warning",
 15     "Error"};
 16 
 17 std::ostream &Log(std::string message, int level)
 18 {
 19     std::cout << " | " << (unsigned)time(nullptr)
 20     << " | " << mgs[level] << " | "<

所需头文件

 1 #pragma once                                                                                                                    
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include"Log.hpp"
  8 #include
  9 #include
 10 using namespace std;
 11 #define SIZE 4096
 12 #define PATH_NAME "."
 13 #define PROJ_ID 0x66
 14 
 15 
 16 string TransToHex(key_t k)
 17 {
 18     char buffer[32];
 19     snprintf(buffer,sizeof(buffer),"0x%x",k);
 20     return buffer;
 21 }

接收方代码

#include"comm.hpp"
  2 
  3 int main()
  4 {
  5     // 1.创建公共key
  6     key_t k=ftok(PATH_NAME,PROJ_ID);
  7     assert(k!=-1);
  8     Log("create key done",Debug)<<" sgmrevice key: "<< TransToHex(k)<

发送方代码

 1 #include"comm.hpp"                                                                                                                                                                                                               
  2 int main()
  3 {         
  4   //获取k值
  5   key_t k=ftok(PATH_NAME,PROJ_ID);
  6   assert(k!=-1);                  
  7   (void)k;                        
  8   Log("create key done  郑建云",Debug)<<"key:"<

执行顺序必须先执行接收代码,因为接收代码必须先创建好共享内存,然后发送方才可以链接。

否者,发送方先建立了,在执行中接收方将检查出内存中已经存在该key的共享内存,直接报错,返回一个-1到shmid。

你可能感兴趣的:(数据结构)