搭建网站要哪些知识,企业服务中心抖音,网站建设需要材料,网页制作网站开发#x1f4d6; 前言#xff1a;本期介绍共享内存。 目录 #x1f552; 1. 共享内存的原理#x1f552; 2. 共享内存的概念#x1f558; 2.1 接口认识#x1f558; 2.2 演示生成key的唯一性#x1f558; 2.3 再谈key #x1f552; 3. 共享内存相关命令#x1f552; 4. 利… 前言本期介绍共享内存。 目录 1. 共享内存的原理 2. 共享内存的概念 2.1 接口认识 2.2 演示生成key的唯一性 2.3 再谈key 3. 共享内存相关命令 4. 利用共享内存进行进程间通信 5. 共享内存的优缺点 1. 共享内存的原理
在之前学过的进程地址空间的基础上我们知道进程之间具有独立性因为每个进程的内核数据结构的数据以及页表的映射都是独立的。而对于共享内存我们同样了解这是为了让进程之间能够进行通信的公共空间接下来就通过进程地址空间的结构去了解共享空间的位置及原理
OS为了让两个毫不相关的进程之间进行通信进行了三个工作
在对应的内存当中让用户帮OS申请一块空间通过指定的调用接口将创建好的内存映射进进程的地址空间用户就可以通过访问起始地址的方式来进行对申请的这块内存空间的访问未来不想通信 取消进程和内存的映射关系释放内存
因此我们把申请的这块空间称之为共享内存将映射关系称之为进程和共享内存进行挂接。将取消进程和内存的映射关系称之为去关联释放内存释放的就是共享内存。
理解
进程间通信是专门设计的用来IPC的和malloc/new不是一个东西。共享内存是一种通信方式所有想通信的进程都可以用。OS中一定会存在着很多共享内存。 2. 共享内存的概念
通过让不同的进程看到同一个内存块的方式叫做共享内存。 2.1 接口认识
#includesys/ipc.h
#includesys/shm.hint shmget(key_t key, size_t size, int shmflg);// size:共享内存的大小对于shmflg常见的有两种选择
IPC_CREAT如果不存在共享文件则创建存在则获取IPC_EXCL 无法单独使用单独使用没有意义需要结合IPC_CREATIPC_CREAT|IPC_EXCL如果不存在就创建如果已存在就出错返回。即在用户的角度如果创建成功一定是一个新的shm
shmget返回值 记住他是一个标识符就够用了得到的是共享内存的标识符。和文件fd没有任何关系
key 是什么不重要最重要的是其具备的唯一性。
而获取key值则通过一个新的接口ftok ftok通过指定的字符串数据*pathname以及char类型的proj_id数据进行一系列的算法整合返回了具有唯一性的Key:
key_t ftok(char *pathname, char proj_id);由于创建的key值有可能已经被别人使用了因此有失败的可能性。创建Key值如果失败则返回-1。 2.2 演示生成key的唯一性
# Makefile
.PHONY:all
all:shm_client shm_servershm_client:shm_client.ccg -o $ $^ -stdc11
shm_server:shm_server.ccg -o $ $^ -stdc11.PHONY:clean
clean:rm -f shm_client shm_server// comm.hpp
#ifndef _COMM_HPP_
#define _COMM_HPP_#includeiostream
#includecerrno
#includecstdlib
#includecstring
#includecstdio
#includesys/ipc.h
#includesys/shm.h#define PATHNAME .//当前路径
#define PROJ_ID 0x66key_t getKey()
{key_t k ftok(PATHNAME, PROJ_ID);if(k 0){// cin, cout, cerr -stdin, stdout, stderr-0, 1, 2;标准错误stderr向2打印。std::cerr errno : strerror(errno) std::endl;exit(1);//终止进程}return k;
}#endif// shm_server.cc
#includecomm.hppint main()
{key_t k getKey();printf(0x%x\n, k);return 0;
}// shm_client.cc
#includecomm.hppint main()
{key_t k getKey();printf(0x%x\n, k);return 0;
}[hinsVM-12-13-centos shm]$ ./shm_server
0x6601062a
[hinsVM-12-13-centos shm]$ ./shm_client
0x6601062a通过make后执行发现两个程序的k值是一样的这就证明了ftok指定参数的返回值是唯一的。k实际上就是32位的一个整数 2.3 再谈key
OS中一定存在多个共享内存因为彼此之间可能都需要通信因此也就都需要申请一块空间。而OS申请的共享空间也一定和进程一样需要被管理既然需要管理那么一定也是先描述再组织的方式即共享内存 物理内存块共享内存的相关属性 。
之前谈到过key是什么不重要能进行唯一性的标识最重要因此创建共享内存的时候是如何保证共享内存在系统中是唯一的呢当然是通过key来确定的只要一个进程也看到了同一个key就能够访问这个共享内存。那么key在哪里实际上这就和PCB一样key就在内核中的属性集合里即
struct shm{key_t key;//...
}即key是通过shmget这样的系统调用设置进入共享内存属性中用来表示该共享内存在内核中的唯一性
shmid和key就好比fd和inode。为什么有了key还需要shmid呢通过key和shmid的区分能够面向系统层面和用户层面这样能够更好的进行解耦以免内核中的变化影响到用户级。 3. 共享内存相关命令
通过让不同的进程看到同一个内存块的方式叫做共享内存。
查看共享内存ipcs -m/-q/-s 共享内存/消息队列/信号量数组
删除共享内存ipcrm -m shmnid
将共享内存与虚拟内存进行关联:
#include sys/types.h
#include sys/shm.h
void *shmat(int shmid, const void *shmaddr, int shmflg);// 共享内存id被映射的进程地址空间给nullptr给0默认可以读写。成功时将返回共享内存的虚拟地址。失败返回-1失败错误码errno被设置 将共享内存与虚拟内存去关联
#include sys/types.h
#include sys/shm.h
int shmdt(const void *shmaddr);//参数shmat的返回值。成功时将返回0。失败返回-1失败错误码errno被设置控制主要用移除共享内存shmctl
#include sys/ipc.h
#include sys/shm.h
int shmctl(int shmid, int cmd, struct shmid_ds *buf);//shmid(类似fd),传入系统设定的宏shmid_ds数据结构。传入IPC_RMID移除共享内存成功时将返回0。失败返回-1失败错误码errno被设置4. 利用共享内存进行进程间通信
// comm.hpp
#pragma once
#include iostream
#include cerrno
#include cstring
#include cstdlib
#include cstdlib
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/shm.h#define PATHNAME .//当前路径路径都行
#define PROJ_ID 0X55//项目id也无要求
#define MAX_SIZE 4096
key_t getKey()
{key_t kftok(PATHNAME, PROJ_ID);if(k-1){std::coutftokerrno:strerror(errno)std::endl;exit(1);}return k;
}
int getShmHelper(key_t key,int flags)
{int shmidshmget(key,MAX_SIZE,flags);if(shmid-1)//创建共享内存失败{std::cerrshmgeterrno:strerror(errno)std::endl;exit(2);}return shmid;//返回共享内存标识符
}
int getShm(key_t key)//创建||获取共享内存
{return getShmHelper(key,IPC_CREAT);//传0也行
}
int createShm(key_t key)//必定创建共享内存
{return getShmHelper(key,IPC_CREAT|IPC_EXCL|0600);//生成一个全新的共享内存
}
void* attachShm(int shmid)//让共享内存与虚拟内存建立联系
{void* memstartshmat(shmid,nullptr,0);if((long long)memstart-1L){std::cerrshmaterrno:strerrorstd::endl;exit(3);}return memstart;
}
void detchShm(void* memStart)//去关联
{if(shmdt(memStart)-1){std::cerrshmdterrno:strerrorstd::endl;exit(4);}
}
void delShm(int shmid)//删除共享内存
{if(shmctl(shmid,IPC_RMID,nullptr)-1){std::cerrshmctlerrno:strerrorstd::endl;}
}// shm_server.cc
#include comm.hpp
int main()
{key_t kgetKey();printf(0X%x\n,k);int shmidcreateShm(k);char* memStart(char*)attachShm(shmid);//让共享内存与虚拟内存建立联系printf(memStart address:%p\n,memStart); //通信接收代码while(true){printf(client say:%s\n,memStart); sleep(1);//调用用户级结构体struct shmid_ds ds;//创建结构体对象dsshmctl(shmid,IPC_STAT,ds);//获取ds对象的状态printf(获取属性%d,pid:%d,myself:%d,key:%d\n,ds.shm_segsz,getpid(),ds.shm_cpid,ds.shm_perm.__key);}detchShm(memStart);//去关联sleep(10);delShm(shmid);//删除共享内存,client和server都能删除共享内存尽量谁创建谁删return 0;
}// shm_client.cc
#include comm.hpp
int main()
{key_t kgetKey();printf(0X%x\n,k);int shmidgetShm(k);//获取共享内存sleep(5);char* memStart(char*)attachShm(shmid);//让共享内存与虚拟内存建立联系printf(memStart address:%p\n,memStart); //通信传输代码const char* massageI am client;pid_t idgetpid();int cnt0;//发送计数while(true){snprintf(memStart,MAX_SIZE,%s[%d]:%d\n,massage,getpid,cnt);sleep(1);}detchShm(memStart);//去关联return 0;
}5. 共享内存的优缺点
优点共享内存是所有进程间通信中速度最快的。无需缓冲区能大大减少通信数据的拷贝次数
缺点如果服务端读取速度较快用户端发送数据较慢就会产生同一段消息被服务端读取多遍。共享内存是不进行同步和互斥的没有对数据进行任何保护。
共享内存大小的建议因为系统分配共享内存是以4KB为基本单位一般建议申请共享内存的大小为4KB的整数倍。 OK以上就是本期知识点“共享内存”的知识啦~~ 感谢友友们的阅读。后续还会继续更新欢迎持续关注哟~ 如果有错误❌欢迎批评指正呀~让我们一起相互进步 如果觉得收获满满可以点点赞支持一下哟~ ❗ 转载请注明出处 作者HinsCoder 博客链接 作者博客主页