合肥市庐阳区住房和城乡建设局网站花卉网站建设推广
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:57
当前位置: 首页 > news >正文
合肥市庐阳区住房和城乡建设局网站,花卉网站建设推广,网站建设规划设计方案,短视频seo排名系统My poor lost soul上章花了不少的篇幅讲了讲基于管道((匿名、命名))技术实现的进程间通信。进程为什么需要通信#xff1f;目的是为了完成进程间的协同,提高处理数据的能力、优化业务逻辑的实现等等#xff0c;在linux中我们已经谈过了一个通信的大类…My poor lost soul上章花了不少的篇幅讲了讲基于管道((匿名、命名))技术实现的进程间通信。进程为什么需要通信目的是为了完成进程间的协同,提高处理数据的能力、优化业务逻辑的实现等等在linux中我们已经谈过了一个通信的大类——管道。根据System V标准的基础上提出了另一套进程通信的标准。—–前言一、System V简介System V曾经也被称为ATTSystem V是Unix操作系统众多版本中的一支。System V的第一个版本发布于1983年。它引进了一些特性例如vi编辑器和curses库。其中也包括了对DEC VAX机器的支持。同时也支持使用消息进行进程间通信信号量和共享内存。 取自这里为什么这么隆重地介绍System V呢因为这是一套通信标准。当在后面学了共享内存的多个API后你会发现消息队列、信号量的接口函数极为相似。二、共享内存共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候其它进程都会察觉到这个更改。 取自这里文字描述显然很恼人我们直接上图。通信的本质就是让不同能够看到同一份资源。由此我们对共享内存的理解是其本质就是开辟在物理内存里的一块内存块用来进行IPC通信的。让需要通信的进程能够看到这块内存块并在上面进行通信行为。三、实现共享内存(1)创建共享内存块#include sys/ipc.h #include sys/shm.h int shmget(key_t key, size_t size, int shmflg);shmget() returns the identifier of the System V shared memory segment associated with the value of the argument key. A new shared memory segment, with size equal to the value of size rounded up to a multiple of PAGE_SIZE, is created if key has the value IPC_PRIVATE or key isnt IPC_PRIVATE, no shared memory segment corresponding to key exists, and IPC_CREAT is specified in shmflg.这里也就简单说说shmget的参数。key:这个参数至关重要。它是连接共享内存找到共享内存块的关键。也就是说一个进程只要拿到了在这个key值就可以访问这一块内存块。size:申请共享内存块的大小。这个size会按照PAGE_SIZE大小(向上对齐)。shmflg:我们常用的参数就是 IPC_CREATE \ IPC_EXCL:IPC_CREATE:如果不存在就创建、如果存在就获取IPC_EXCL:不能单独使用。IPC_CREATE | IPC_EXCL 如果不存在就创建存在就返回错误(保证给用户的共享内存块一定是新创建的)。如果创建成功shmget会返回一个有效标记内存块的标识符那么怎么形成key这个唯一标识的关键字呢库里给我们提供了一个函数可以让生成的key是一个唯一标识的数字key_t类型。#include sys/types.h #include sys/ipc.h key_t ftok(const char *pathname, int proj_id);convert a pathname and a project identifier to a System V IPC key用pathname proj_id转换为key并且这个pathname不是随便乱取的。而是一个现有、可访问的文件。如何让两个进程看到一块共享内存只需要知道key就行了。key是怎么生成的ftok(pathname,proj_id)。这两个参数一样不久可以生成相同的key了嘛如何理解key?在操作系统中一定会存在多个key_t类型的 有效标识符。那么这么多标识符一定会被操作系统管理。管理的本质:先描述、再组织。我们举个例子我们可以看到OS会为共享内存块维护一份结构体struct shimid_ds 用来管理共享内存块。共享内存的生命周期随OS:我们在学习管道通信时一旦进程有一方结束那么双方的通信管道也会随之关闭。为什么现如今进程结束了它们申请的共享内存块仍然存在呢管道的生命周期随进程共享内存的生命周期随OS。为此我们不得不手动去关闭掉我们编写的进程所打开的共享内存块。ipcrm -m shmid(2)挂接与去关联我们现如今拿到了共享内存块的标识符shmid那么如何通过这个shmid找到共享内存的位置呢#include sys/types.h #include sys/shm.h void *shmat(int shmid, const void *shmaddr, int shmflg);shmat() attaches the System V shared memory segment identified by shmid to the address space of the calling process. The attaching address is specified by shmaddr with one of the following criteria.通过这个函数可以通过shmid 与 共享内存块挂接并返回该共享内存块的地址。参数: shmaddr 、shmflagIf shmaddr is NULL, the system chooses a suitable (unused) address at which to attach the segment.这里我们通常设置为 nullptr那么OS就会为我们选择一个适合的挂接到了这个内存块的地址。shmflag通常为设置为0.返回参数 On success shmat() returns the address of the attached shared memory segment; on error (void *) -1 is returned, and errno is set to indicate the cause of the error.如果成功shmat()返回挂接这个共享内存块的地址返回-1是error的void *attachShm(int shmid) {void *mem shmat(shmid, nullptr, 0);if ((long long)mem -1) // Linux下 是64位系统 一个指针大小为8字节{std::cerr attachShm: mem std::endl;exit(3);}return mem; }#include sys/types.h #include sys/shm.h int shmdt(const void shmaddr);shmdt() detaches the shared memory segment located at the address specified by shmaddr from the address space of the calling process. The to-be-detached segment must be currently attached with shmaddr equal to the value returned by the attaching shmat() call.shmdt()会将传入的共享内存块地址去挂接(关联)。调用shmdt(),必须传入通过shmat()获取的地址。On success shmdt() returns 0; on error -1 is returned, and errno is set to indicate the cause of the error.0为去关联成功-1位失败。void detachShm(void start) {int ret shmdt(start);if(ret -1){std::cerr attachShm: ret std::endl;exit(4);} }(3)释放共享内存块共享内存块的生命周期随OS我们每申请共享内存空间都得ipcrm -m shmid释放内存空间当我们不再使用时这未免太过麻烦了。#include sys/ipc.h #include sys/shm.h int shmctl(int shmid, int cmd, struct shmid_ds *buf);shmctl() performs the control operation specified by cmd on the System V shared memory segment whose identifier is given in shmid.shmctl()通过cmd传入的命令操作对shmid表示的共享内存块进行处理。要在进程结束时关闭共享内存我们需要传入的参数是: IPC_RMID Mark the segment to be destroyed.void delShm(int shmid) {if (shmctl(shmid, IPC_RMID, nullptr) -1){std::cerr delShm: shmid std::endl;exit(5);} }当然shmctl不仅仅可以归还共享内存当cmd传入的参数是IPC_STAT时我们可以获取由shmid填充的结构体内容。像这样:int main() {int shmid shmget(key);struct shmid_ds ds;shmctl(shmid,IPC_STAT,ds);ds.shm_perm.__key;ds.shm_atime;//..return 0; }(4)测试有了上面对函数的理解和实现我们可以进行一定的通信了。我们想让Sever读取client发送的内容: Hello Server! pid 发送次数。Client:int main() {// 1.申请keykey_t key getKey(PATH_NAME, PROJ_ID);std::cout Client key: key std::endl;// 2.申请内存块int shmid getShm(key);std::cout Client shmid: shmid std::endl;// 3.挂接void start attachShm(shmid);printf(attach success, address start: %p\n, start);// 真正的通信区域const char msg Hello Server!;int cnt 0;while (true){ snprintf((char*)start,MAX_PAGE,%s[pid:%d]编号信息:[%d]\n,msg,getpid(),cnt);sleep(1);}// 4.去关联detachShm(start);return 0; }Server:int main() {// 1.申请keykey_t key getKey(PATH_NAME, PROJ_ID);std::cout Server key: key std::endl;// 2.申请内存块int shmid createShm(key);std::cout Server shmid: shmid std::endl;// 3.挂接void *start attachShm(shmid);printf(attach success, address start: %p\n, start);// 真正的通信区域while (true){printf(client say : %s\n, start);sleep(1);}// 4.去关联detachShm(start);printf(detach success);// 5.关闭共享内存delShm(shmid);return 0; }我们来看看效果吧~这是怎么回事噢原来是权限问题。我们在创建共享内存的时候需要附上权限大小。这样就完成了双方进程间的通信。四、共享内存 vs 管道但是管道自带同步与互斥如果写端不写入读端会成阻塞状态直到写端写入此时有数据可读。但是共享内存不一样它没有同步与互斥操作即便写端没有写入数据读端照样会向内存块中读取。总结:①共享内存是一块存在物理内存的由操作系统管理的内存块。它属于IPC通信方式的一种在所有的通信方式中速度是最快的。②共享内存的创建:1.申请(shmget) 2.挂接(shmat) 3.去关联(shmdt) 4.关闭空间(shmctl).③管道自带同步与互斥共享内存不支持。本篇也就告一段落了感谢你的阅读。祝你好运~向阳而生。
- 上一篇: 合肥市城乡建设局网站东阿做网站
- 下一篇: 合肥市门户网站wordpress应用中心
相关文章
-
合肥市城乡建设局网站东阿做网站
合肥市城乡建设局网站东阿做网站
- 技术栈
- 2026年03月21日
-
合肥企业做网站销售助手app最新版本
合肥企业做网站销售助手app最新版本
- 技术栈
- 2026年03月21日
-
合肥企业网站建设专家芜湖市网站开发
合肥企业网站建设专家芜湖市网站开发
- 技术栈
- 2026年03月21日
-
合肥市门户网站wordpress应用中心
合肥市门户网站wordpress应用中心
- 技术栈
- 2026年03月21日
-
合肥市网站建设 小程序建设银行普卡申请网站
合肥市网站建设 小程序建设银行普卡申请网站
- 技术栈
- 2026年03月21日
-
合肥网站策划网站多大需要服务器
合肥网站策划网站多大需要服务器
- 技术栈
- 2026年03月21日
