当前位置: 首页 > news >正文

网站建设和维护教程定制app开发

网站建设和维护教程,定制app开发,湖南城乡建设厅官方网站,金山区网站制作文章目录 #x1f4d6; 前言1. 共享内存2. 创建共享内存2.1 ftok()创建key值#xff1a;2.2 shmget()创建共享内存#xff1a;2.3 ipcs指令#xff1a;2.4 shmctl()接口#xff1a;2.5 shmat()/shmdt()接口:2.6 共享内存没有访问控制#xff1a;2.7 通过管道对共享内存进… 文章目录 前言1. 共享内存2. 创建共享内存2.1 ftok()创建key值2.2 shmget()创建共享内存2.3 ipcs指令2.4 shmctl()接口2.5 shmat()/shmdt()接口:2.6 共享内存没有访问控制2.7 通过管道对共享内存进行控制 3. 相关概念 前言 上一章我们由进程通信引入并讲述了管道匿名管道和命名管道和匿名管道。本章我们将继续讲解进程通信的另一种方式通过共享内存的方式来进行进程间的通信。还要学习几个系统调用接口并用代码实现两个进程通过共享内存来进行通信。目标已经确定接下来就要搬好小板凳准备开讲了… 本章讲的是system V的共享内存。 1. 共享内存 之前我们学习进程地址空间时就已经对进程地址空间的构成有了相对的认识【进程地址空间 - 复习】 我们知道堆栈相对而生堆从低地址向高地址生长栈从高地址向低地址生长而在这两块空间之间的则是共享区。堆栈之间的区域特别大堆栈之间的区域称为共享区其中共享库就在这里。 假设有种接口 能在物理内存创建空间。通过两个进程调用接口然后物理内存中的空间映射到自己的地址空间上然后将空间的起始地址返回给用户此时用户就能通过页表找到物理内存的空间。 此时两个进程各自都完成了第一步创建共享内存第二步分别将共享内存挂接到各自的进程上下文里面。 进程间通信的前提是先让不同的进程看到同一份资源 共享内存是一种进程间通信机制它允许多个进程共享同一块物理内存区域就能同时看到一份资源。当一个进程向共享内存写入数据时实际上是将数据直接写入到共享内存所对应的物理内存中。其他进程可以通过读取相同的共享内存区域来获取已写入的数据。 优点 与其他进程间通信方式如管道、消息队列等不同。共享内存避免了数据的复制和传输过程因此具有较高的效率。它可以提供快速的数据交换特别适用于需要频繁共享大量数据的进程间通信场景。 2. 创建共享内存 2.1 ftok()创建key值 共享内存存在哪里 内核中 —— 内核会给我们维护共享内存的结构共享内存也要被管理起来一定是先描述再组织 系统中可能有很多对进程都在用共享内存通信所以操作系统也要将它们管理起来。 我怎么知道这个共享内存是存在还是不存在 先有方法标识共享内存的唯一性共享内存在内核中让不同的进程看到同一份共享内存。做法是让他们拥有同一个key即可 解释 每个共享内存都是由一个唯一的key值来标识的。在操作系统中共享内存是进程间进行通信的一种方式它允许多个进程共享同一块物理内存区域。为了实现这种共享操作系统会给每个共享内存区域分配一个唯一的key值来标识它其他进程可以通过这个key值来访问并操作该共享内存区域。这样就可以实现多个进程之间的数据交换和共享。 在共享内存里只要保证这个key是唯一的就可以了。至于这个key是多少不重要。 创建key值的函数 Linux系统给定了ftok接口将用户提供的pathname工作路径以及proj_id项目编号转换为一个共享内存的key其实就是int类型。 底层会将第一个参数对应路径文件的inode和指定的项目id这两个数字做组合形成一个唯一值返回给一个key。底层是一些列的算法设计相当于是帮我们构建具有唯一性的数字就可以了。 返回值 成功了返回key值失败了就返回-1。 2.2 shmget()创建共享内存 使用前提是要有一个唯一的key值 第二个参数建议设置成页4KB的整倍数 操作系统和磁盘lO的基本单位大小是4KB。从磁盘拷贝到内存是以4KB为单位拷贝的。所以共享内存在申请大小时也一定是4KB的整数倍。操作系统只会按照整4KB来申请共享内存是向上取整。 如果我们申请的是4097那么操作系统申请的是8KB但是我们只能用4097因为只要了这么多。 shmflg的设置 IPC_CREAT创建共享内存如果已经存在就获取之不存在就创建之。 获取可以获取成功但是不知道这个共享内存是本进程创建还是别的进程创建的拿过来的。 IPC_EXCL必须配合IPC_CREAT使用用按位或|配合使用如果不存在指定的共享内存创建之如果存在了出错返回。 核心作用 可以保证如果shmget函数调用成功一定是一个全新的share memory共享内存。 如果这两个选项合着一起配合使用一起传 只要函数调用成功了得到的一定是个全新的共享内存。 0666或权限值指定共享内存的访问权限。这些权限值使用八进制表示例如0666表示可读可写权限。 返回值 如果成功的话返回一个标志符号如果失败的话返回-1errno被设置。 key值是由谁提供 key值得由用户来提供。如果key值是由操作系统统一提供的话 那么调用shmget接口获取共享内存的时候操作系统给一个key值。 另一个进程如何知道该进程key值呢是不可能知道的。 那么就不能确定唯一性了那么不同的应用程序可能会得到相同的key。 这样一来就有可能导致两个或多个应用程序之间共享同一个共享内存段。 这样的共享可能会引发数据混乱、冲突以及安全性问题。 如果key值是由用户提供的话 那么一个进程就可以提供一个key值让操作系统帮它创建一个共享内存并且约定好让其他进程也使用同样的key值。 这二者只要有一个创建了共享内存能够将key值设置在内核里那另一个进程则可以用同样的key值找就可以看到同一个共享内存了。 这就叫做看到了同一份共享资源了。 2.3 ipcs指令 通过上述讲解我们只要获取到唯一的key值调用shmget函数就能获得共享内存了创建好了我们怎样才能知道有哪些IPC资源呢 看一下ipcs指令的几个选项 ipcs -c #查看消息队列/共享内存/信号量 ipcs -s #单独查看信号量 ipcs -q #单独查看消息队列 ipcs -m #单独查看共享内存ipcs -m查看shm list。 key值是十六进制我们创建出来看到的则是十进制。nattch是挂接上的进程的数量。bytes是申请的共享内存大小。 ipcrm -m 删除共享内存 只要在指令后跟上自己要删除的共享内存的shmid值就可以了 如果不显示删除共享内存那么就只能通过重启云主机的方式来删除共享内存了。 为什么删除共享内存要用shmid而不用key呢 key是操作系统中用来标识共享内存唯一性的 在用户层用的是shmid。在用户层访问共享内存只能用数字shmid。 2.4 shmctl()接口 shmctl这个函数可以用于操作共享内存 第一个参数想对哪个共享内存做操作。第二个参数想对这个共享内存做什么操作。第三个参数如果IPC_RMID如果被设置了shmid_ds设置成nullptr就可以了还有一些其他的属性设置。 第二个参数可以是 IPC_STAT用于获取共享内存段的状态信息包括共享内存段大小、访问权限等。IPC_SET用于设置共享内存段的状态信息如更改访问权限、起始地址等。IPC_RMID用于删除共享内存段释放相关的资源。 此外第二个参数还可以与其他标志进行按位或操作以指定额外的选项或标志例如 IPC_INFO用于获取当前共享内存资源的统计信息。SHM_INFO用于获取当前系统上共享内存段的信息。SHM_STAT用于获取当前共享内存段的详细信息。 2.5 shmat()/shmdt()接口: at是attach的简写把一个共享内存附在进程上。dt是detach的简写把一个共享内存从进程上脱离下来去关联。 返回值 因为shmat函数的返回值是一个void*类型的指针所以我们就可以像使用malloc一样的方式使来挂接共享内存了。随后对这个共享内存的操作就像平时使用数组一样的方式来使用了。 同样的道理另一个进程也需要挂接这个共享内存才能实现两个进程通过共享内存来进行通信。 注意 共享内存是一种特殊的内存区域可以由多个进程同时访问。尽管共享内存由一个进程创建但它并不属于任何一个特定的进程。 2.6 共享内存没有访问控制 在我们之前的学习中知道管道是有访问控制的进程通信方式当写端没有写入数据的时候空管道读端的read接口会进行等待直到有管道中有数据写入。 而共享内存的申请更想是我们直接向操作一个malloc出来的空间一样进程只要有权限就可以直接拿来用不向管道那样是个文件还要通过read/write接口来访问。所以操作系统没有办法帮我们进行访问控制 管道 首先将数据从外设拷贝到进程上下文代码里面。再把代码拷贝到管道里面再调用write把数据拷贝到另一个进程的上下文。再继续还要将数据拷贝到外设里一共至少要经历四次拷贝。 共享内存 写到共享内存里对方立马能看到。用共享内存如果不考虑外设最多拷贝一次一方写入另一方立马能看到。 2.7 通过管道对共享内存进行控制 Log.hpp #pragma once#include iostream #include ctimestd::ostream Log() {std::cout For Debug | timestamp: (uint64_t)time(nullptr) | ;return std::cout; }Comm.hpp #pragma once#include iostream #include cstdio #include cstring #include cerrno #include cstdlib #include cassert #include sys/types.h #include sys/ipc.h #include sys/shm.h #include unistd.h #include sys/stat.h #include sys/fcntl.h #include Log.hppusing namespace std;#define PATH_NAME /home/Zh_Ser/linux #define PROJ_ID 0x14 #define MEM_SIZE 4096#define FIFO_FILE ./.fifo// hpp是将头文件和源文件写在一起的方式 // 函数的定义可以放在里面一般在开源的项目里用key_t CreateKey() {key_t key ftok(PATH_NAME, PROJ_ID);if (key 0){cerr ftok: strerror(errno) endl;exit(1);}return key; }// 创建命名管道 void CreatFifo() {umask(0);if (mkfifo(FIFO_FILE, 0666) 0){Log() strerror(errno) endl;exit(2);} }#define READER O_RDONLY #define WRITER O_WRONLYint Open(const string filename, int flags) {return open(filename.c_str(), flags); }int Wait(int fd) {uint32_t values 0;ssize_t s read(fd, values, sizeof(values));return s; }void Signal(int fd) {uint32_t cmd 1;int s write(fd, cmd, sizeof(cmd)); }void Close(int fd, const string filename) {close(fd);unlink(filename.c_str()); }IpcShmCli.cpp #include Comm.hpp #include Log.hpp// 充当使用共享内存的角色 int main() {int fd Open(FIFO_FILE, WRITER);cout Client: fd endl;// 创建相同的key值key_t key CreateKey();Log() key: key endl;// 等待Server端先创建共享内存sleep(1);// 获取共享内存int shmid shmget(key, MEM_SIZE, IPC_CREAT);if (shmid 0){Log() IpcShmCli shmget: strerror(errno) endl;return 2;}// 挂接char* str (char*)shmat(shmid, nullptr, 0);// sleep(5);// 用它// 用共享内存竟然没有使用任何系统调用接口// 直接向str空间写入while (true){printf(Please Enter# );fflush(stdout);// 往共享内存写数据ssize_t s read(0, str, MEM_SIZE);if (s 0){str[s] \0;}Signal(fd);}// 去关联shmdt(str);// 不需要删除return 0; }IpcShmSer.cpp #include Comm.hpp #include Log.hpp// 创建全新的共享内存 const int flags IPC_CREAT | IPC_EXCL;// 充当创建共享内存的角色 int main() {// 创建管道CreatFifo();int fd Open(FIFO_FILE, READER);cout Server: fd endl;assert(fd 0);// 创建Keykey_t key CreateKey();Log() key: key endl;Log() create share memory begin endl;int shmid shmget(key, MEM_SIZE, flags | 0666);if (shmid 0){Log() IpcShmSer shmget: strerror(errno) endl;return 2;}Log() create shm success, shmid: shmid endl;// 1. 将共享内存和自己的进程产生关联attchchar* str (char*)shmat(shmid, nullptr, 0);Log() attach shm: shmid success endl;// 用它// 服务器端直接用while (true){sleep(1);// 在管道当中等让读端进行等待if (Wait(fd) 0) break;// 从共享内存里读数据printf(%s\n, str);}// 2. 去关联shmdt的返回值就是shmat的返回值shmdt(str);Log() detach shm: shmid success endl;// 删除shmctl(shmid, IPC_RMID, nullptr);Log() delete shm: shmid success endl;Close(fd, FIFO_FILE);return 0; }我们先执行服务端再执行用户端我们会发现一个现象服务端会等待当用户端启动后两边才开始都跑起来。 这是open接口的阻塞等待重点 在使用open函数打开一个FIFO命名管道时如果以只写/读方式打开并且没有其他进程以读/写模式打开相同的FIFO则会发生阻塞。这是因为FIFO命名管道是基于进程间通信的一种机制要求读和写操作成对出现。 对于一个命名管道FIFO只有在读端和写端同时打开之后open函数才会返回。 也就是说当一个进程以只读方式打开FIFO而另一个进程以只写方式打开相同的FIFO时两个进程都完成打开操作后它们之前的阻塞状态将被解除。 解释重点 当你以只读方式打开FIFO时如果没有其他进程以写模式打开相同的FIFO则读取操作会一直等待。同样地当你以只写方式打开FIFO时如果没有其他进程以读模式打开相同的FIFO则写入操作会一直等待。只有在读端和写端都成功打开之后两个进程之间的通信才能顺利进行。这种机制确保了读和写操作的同步保证了数据的正确传输。因此当你使用open函数打开一个FIFO时要确保读端和写端都已经打开才能结束等待并进行进一步的读写操作。 如果是同一个key第一个进程用shmget第三个参数是IPC_CREAT第二个进程用shmget第三个参数是IPC_CREAT | IPC_EXCL那么第二个进程会创建共享内存失败。 如果第一个进程在创建共享内存时使用了shmget函数的第三个参数为IPC_CREAT则表示如果共享内存不存在就创建一个新的。而第二个进程在创建共享内存时使用了IPC_CREAT | IPC_EXCL即同时设置了IPC_CREAT和IPC_EXCL表示如果共享内存已经存在则返回错误。因此在这种情况下如果第一个进程已经创建了共享内存那么第二个进程会因为IPC_EXCL的设置而无法再次创建共享内存shmget函数会返回一个错误第二个进程创建共享内存失败。这样可以确保同一个key只能被一个进程创建共享内存防止重复创建和竞争条件的发生。 所以正因为有shmget函数第三个参数这样的机制我们必要时要让参数是IPC_CREAT的进程等一下参数是IPC_CREAT | IPC_EXCL的进程让后者先把共享内存创建好了前者直接获取。 若是前者先创建共享内存后者一旦判断同一个key值已经创建好了一块共享内存就会返回错误。除非两个shmget函数第三个参数都是IPC_CREAT这样无论哪个进程先创建共享内存另一方都可以获取到对方创建的共享内存。 通过共享内存进程通信结果 基于共享内存 管道的一个访问控制的效果 管道本身提供保护机制我们自己也做了一次保护机制共享内存 管道的机制。如果这两个方案都不提供裸的共享内存被双方同时看到。我们两个进程在操作就可能出现一些来回读写交叉的问题。导致数据不一致的问题或者是访问控制方面的问题。 3. 相关概念 临界资源 被多个进程能够看到的资源叫做临界资源。 如果没有对临界资源进行任何保护对于临界资源的访问。双方进程在进行访问的时候就都是乱序的。可能会因为读写交叉而导致的各种乱码、废弃数据、访问控制方面的问题临界资源有安全的也有不安全的取决于内部是否做了保护。 临界区 对多个进程而言访问临界资源的代码。 我的进程代码中有大量的代码只有一部分代码会访问临界资源。两个进程分别对共享资源做读写的代码叫做它们俩的临界区。 原子性 我们把一件事情要不没做要么做完了叫原子性。 没有中间状态。 互斥 任何时刻只允许一个进程访问临界资源。
http://www.dnsts.com.cn/news/237196.html

相关文章:

  • 企业宣传网站多大主机营销型网站建立
  • 西部数码网站管理助手3.0教程广告设计图片大全 模板
  • 怎么创建免费网站吗wordpress添加会员登录页面
  • 网站建设管理员郑州seo优化阿亮
  • 国内做的比较简洁的网站专业装修图片
  • 做么网站有黄电脑网页版微信
  • 北京企业建站程序sae wordpress 上传
  • 人是用什么做的视频网站网站建设设计师
  • 旅游门户网站模板下载网店代运营费用
  • 设计网站猪八戒网站云优化
  • 淘宝客网站做seo有用吗如何用域名做网站访问
  • gis网站开发教程网页设计毕业设计开题报告
  • 杭州网站的制作wordpress 好主题哦
  • 德州做网站多少钱代理做网站的合同
  • 网站改版好吗天心区网站建设公司
  • 做平面资源比较好的网站做能收款的网站多少钱
  • 洛阳网站在哪备案网站如何做更新
  • 网站管理员权限有哪些wordpress版权信息修改
  • 房产网站如何做徐州seo全网营销
  • 河南如何建网站要什么条件seo公司怎么推广宣传
  • 科普网站栏目建设方案在线网站cms识别
  • seo优化公司排名优化内容
  • 网站建设推广刺盾云成品在线短视频免费入口
  • 赤峰市建设局网站帝国cms如何做网站地图
  • 网站建设的主要内容包括门户
  • 手机网站设置方法效果图培训
  • html+jsp个人网站模板抚顺网站建设
  • 做装修那个网站好有哪些做问卷调查赚钱的网站6
  • 邯郸哪个公司做网站好国内免费设计素材网站
  • 网站架设自己可以开发一个软件吗