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

企业网站官网赣州网吧

企业网站官网,赣州网吧,网站流量狂刷器,浙江省建设网证书查询目录 system V共享内存 共享内存示意图 共享内存函数 shmget函数 shmat函数 shmdt函数 shmctl函数 代码示例 shm头文件 构造函数 获取key值 创建者的构造方式 GetShmHelper 函数 GetShmUseCreate 函数 使用者的构造方式 GetShmForUse 函数 分离附加操作 DetachShm 函数 AttachS… 目录 system V共享内存 共享内存示意图 共享内存函数 shmget函数 shmat函数 shmdt函数 shmctl函数 代码示例 shm头文件 构造函数 获取key值 创建者的构造方式 GetShmHelper 函数 GetShmUseCreate 函数 使用者的构造方式 GetShmForUse 函数 分离附加操作 DetachShm 函数 AttachShm 函数 RoleToString 析构函数 客户端 服务端 命名管道与共享内存的区别 一、定义与工作原理 二、性能与效率 三、使用场景与限制 四、实现与操作 system V共享内存 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间这些进程间数据传递不再涉及到内核换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。 共享内存示意图 共享内存在我们的虚拟地址空间的共享区当中这意味着它一旦通信建立一有数据就能一下被拿到。 共享内存函数 shmget函数 功能用来创建共享内存 原型int shmget(key_t key, size_t size, int shmflg); 参数key:这个共享内存段名字size:共享内存大小shmflg:由九个权限标志构成它们的用法和创建文件时使用的mode模式标志是一样的 返回值成功返回一个非负整数即该共享内存段的标识码失败返回-1 shmat函数 功能将共享内存段连接到进程地址空间 原型void *shmat(int shmid, const void *shmaddr, int shmflg); 参数shmid: 共享内存标识shmaddr:指定连接的地址shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY 返回值成功返回一个指针指向共享内存第一个节失败返回-1 说明 shmaddr为NULL核心自动选择一个地址 shmaddr不为NULL且shmflg无SHM_RND标记则以shmaddr为连接地址。 shmaddr不为NULL且shmflg设置了SHM_RND标记则连接的地址会自动向下调整为SHMLBA的整数倍。公式shmaddr - (shmaddr % SHMLBA) shmflgSHM_RDONLY表示连接操作用来只读共享内存 shmdt函数 功能将共享内存段与当前进程脱离 原型int shmdt(const void *shmaddr); 参数shmaddr: 由shmat所返回的指针 返回值成功返回0失败返回-1 注意将共享内存段与当前进程脱离不等于删除共享内存段 shmctl函数 功能用于控制共享内存 原型int shmctl(int shmid, int cmd, struct shmid_ds *buf); 参数shmid:由shmget返回的共享内存标识码cmd:将要采取的动作有三个可取值buf:指向一个保存着共享内存的模式状态和访问权限的数据结构 返回值成功返回0失败返回-1 代码示例 shm头文件 #ifndef _SHM_HPP_ #define _SHM_HPP_#include iostream #include cstdio #include cerrno #include string #include sys/types.h #include sys/stat.h #include unistd.h #include fcntl.h #include sys/ipc.h #include sys/shm.h #include string.h#define Creater 1 #define User 2 const int gShmSize 4096; const std::string gpathname /home/lsf/lesson24/shm; const int gproj_id 0x66;class Shm { private:key_t GetCommKey(){key_t k ftok(_pathname.c_str(), _proj_id);if (k 0){perror(ftok);}return k;}int GetShmHelper(key_t key, int size, int flag){int shmid shmget(key, size, flag);if (shmid 0){perror(shmget);}return shmid;}std::string RoleToString(int who){if (who Creater)return Creater;else if (who User)return User;elsereturn None;}void *AttachShm(){if (_addrshm ! nullptr)DetachShm(_addrshm);void *shmaddr shmat(_shmid, nullptr, 0);if (shmaddr nullptr){perror(shmat);}std::cout who: RoleToString(_who) attach shm... std::endl;return shmaddr;}void DetachShm(void *shmaddr){if (shmaddr nullptr)return;shmdt(shmaddr);std::cout who: RoleToString(_who) detach shm... std::endl;}public:Shm(const std::string pathname, int proj_id, int who): _pathname(pathname), _proj_id(proj_id), _who(who), _addrshm(nullptr){_key GetCommKey();if (_who Creater)GetShmUseCreate();else if (_who User)GetShmForUse();_addrshm AttachShm();std::cout shmid: _shmid std::endl;std::cout _key: ToHex(_key) std::endl;}std::string ToHex(key_t key){char buffer[128];snprintf(buffer, sizeof(buffer), 0x%x, key);return buffer;}bool GetShmForUse(){if (_who User){_shmid GetShmHelper(_key, gShmSize, IPC_CREAT);// sleep(10);if (_shmid 0){std::cout shm get done... std::endl;return true;}}return false;}bool GetShmUseCreate(){if (_who Creater){_shmid GetShmHelper(_key, gShmSize, IPC_CREAT | IPC_EXCL | 0666);// sleep(10);if (_shmid 0){std::cout shm create done... std::endl;return true;}}return false;}void *Addr(){return _addrshm;}void Zero(){if (_addrshm){memset(_addrshm, 0, gShmSize);}}~Shm(){if (_who Creater){int res shmctl(_shmid, IPC_RMID, nullptr);}std::cout shm remove done... std::endl;}private:key_t _key;int _shmid;std::string _pathname;int _proj_id;int _who;void *_addrshm; };#endif 成员变量中除了_pathname和_who一个表示路径名一个表示身份外其余的都是我们上文提到的函数的参数我们遇到时一一讲解。 构造函数 Shm(const std::string pathname, int proj_id, int who): _pathname(pathname), _proj_id(proj_id), _who(who), _addrshm(nullptr){_key GetCommKey();if (_who Creater)GetShmUseCreate();else if (_who User)GetShmForUse();_addrshm AttachShm();std::cout shmid: _shmid std::endl;std::cout _key: ToHex(_key) std::endl;} 我们分别将我们的路径_proj_id后面说身份_addeshm这些能设的初始值先设置好。然后我们就可以先获得一个我们共享内存的key标识值为什么不直接设置而是要写个函数呢这是为了达到我们唯一性的目的我们程序员自己设置的话难免会设置到重复的为了避免它我们就可以用一个ftok函数它会根据我们的路径和_proj_id用一种算法设计出一个key值我们采用它能达到我们心目中的要求。 它的返回值就是我们要的key值。 项目标识符proj_id除了文件路径外ftok()还需要一个项目标识符proj_id。这个标识符的最低有效8位将被用于生成键值。proj_id必须是非零的以确保生成的键值不是全零全零的键值在System V IPC中有特殊含义通常表示无效的键值。 获取key值 key_t GetCommKey(){key_t k ftok(_pathname.c_str(), _proj_id);if (k 0){perror(ftok);}return k;}这就是我们的获取key值的函数我们只是对ftok简单的封装了一下。 我们回到构造函数在我们完成了key值的设置之后我们就要对创建者和使用则进行不同的构造方式了。 创建者的构造方式 int GetShmHelper(key_t key, int size, int flag){int shmid shmget(key, size, flag);if (shmid 0){perror(shmget);}return shmid;}bool GetShmUseCreate(){if (_who Creater){_shmid GetShmHelper(_key, gShmSize, IPC_CREAT | IPC_EXCL | 0666);// sleep(10);if (_shmid 0){std::cout shm create done... std::endl;return true;}}return false;} GetShmHelper函数就是对我们的shmget函数做个简单封装 GetShmHelper 函数 这个函数根据给定的键值(key)、大小(size)和标志(flag)来获取或创建一个共享内存段。 参数 key_t key共享内存段的键值由ftok()函数生成。int size共享内存段的大小以字节为单位。int flag控制shmget()行为的标志。可以是IPC_CREAT如果键不存在则创建新的共享内存段、IPC_EXCL与IPC_CREAT一起使用时如果键已存在则调用失败等标志的组合。 返回值 成功时返回共享内存段的标识符shmid。失败时返回-1并通过perror()函数打印错误信息。 GetShmUseCreate 函数 这个函数检查某个条件这里是通过_who变量与Creater比较如果条件满足则尝试创建一个新的共享内存段。 变量 _who用于指示当前进程的角色。_key共享内存段的键值。gShmSize共享内存段的大小。_shmid用于存储共享内存段标识符的变量。 逻辑 如果_who等于Creater则调用GetShmHelper函数尝试创建新的共享内存段。GetShmHelper的调用使用了IPC_CREAT | IPC_EXCL | 0666作为标志这意味着如果键值已存在则调用将失败因为IPC_EXCL标志的存在。0666是权限设置但由于IPC_CREAT和IPC_EXCL的存在它实际上只在创建新段时有效。如果GetShmHelper返回非负值即成功创建了共享内存段或获取了已存在的共享内存段则函数返回true。如果GetShmHelper返回-1即失败则函数返回false并且不会打印shm create done...消息。 使用者的构造方式 bool GetShmForUse(){if (_who User){_shmid GetShmHelper(_key, gShmSize, IPC_CREAT);// sleep(10);if (_shmid 0){std::cout shm get done... std::endl;return true;}}return false;} GetShmForUse 函数 目的尝试获取一个共享内存段以供使用。当前角色是用户_who User尝试获取或创建共享内存段。 参数 隐式参数全局变量 _who当前进程的角色。_key共享内存段的键值。gShmSize共享内存段的大小。_shmid用于存储共享内存段标识符的变量。 逻辑 如果_who等于User则调用GetShmHelper函数尝试获取或创建共享内存段。GetShmHelper的调用使用了IPC_CREAT作为标志。这意味着 如果键值对应的共享内存段已存在则shmget将返回该段的标识符。如果键值对应的共享内存段不存在则shmget将创建一个新的共享内存段并返回其标识符。 如果GetShmHelper返回非负值即成功获取了已存在的段或创建了新段则函数返回true打印shm get done...。如果GetShmHelper返回-1即失败这通常不应该发生因为IPC_CREAT允许创建新段。如果_who不是User则函数直接返回false。 分离附加操作 void DetachShm(void *shmaddr){if (shmaddr nullptr)return;shmdt(shmaddr);std::cout who: RoleToString(_who) detach shm... std::endl;}void *AttachShm(){if (_addrshm ! nullptr)DetachShm(_addrshm);void *shmaddr shmat(_shmid, nullptr, 0);if (shmaddr nullptr){perror(shmat);}std::cout who: RoleToString(_who) attach shm... std::endl;return shmaddr;} DetachShm 函数 目的分离detach之前附加attach的共享内存段。 参数 shmaddr指向之前附加的共享内存段的指针。 逻辑 如果传入的shmaddr是nullptr则函数直接返回不执行任何操作。这是一种防御性编程实践用于防止对空指针进行解引用。使用shmdt函数分离共享内存段。shmdt接受一个指向共享内存段的指针并分离该进程与该内存段之间的关联。打印一条消息指示当前角色通过RoleToString(_who)获取正在分离共享内存段。RoleToString是一个将角色转换为字符串的函数。 AttachShm 函数 目的附加attach到一个已存在的共享内存段。 参数无。 逻辑 如果全局变量或类成员变量_addrshm不是nullptr则首先调用DetachShm函数分离当前附加的共享内存段如果有的话。这是一种清理操作确保在附加新的共享内存段之前不会泄漏旧的内存段。使用shmat函数附加到共享内存段。shmat接受共享内存段的标识符、一个指向期望附加地址的指针这里传入nullptr让系统选择地址、以及一组标志这里传入0表示使用默认行为。如果shmat返回nullptr则使用perror函数打印一条错误消息。这意味着附加操作失败可能是由于资源不足、权限问题或其他原因。打印一条消息指示当前角色通过RoleToString(_who)获取正在附加共享内存段。返回shmat返回的指针即指向附加的共享内存段的指针。如果shmat失败则返回nullptr。 RoleToString std::string RoleToString(int who){if (who Creater)return Creater;else if (who User)return User;elsereturn None;} 将_who转换成字符串。 接下来我们可以打印一下共享内存标识符和我们的key值我们将key值转换成十六进制方便观察。 std::string ToHex(key_t key){char buffer[128];snprintf(buffer, sizeof(buffer), 0x%x, key);return buffer;} void *Addr(){return _addrshm;} 我们可以使用这个函数让上层获取共享内存的地址。 void Zero(){if (_addrshm){memset(_addrshm, 0, gShmSize);}} 我们可以用memset将这段共享内存清空。 析构函数 ~Shm(){if (_who Creater){int res shmctl(_shmid, IPC_RMID, nullptr);}std::cout shm remove done... std::endl;} 这里我们也是让创建者把共享内存移除。 int res shmctl(_shmid, IPC_RMID, nullptr);这行代码调用 shmctl 函数尝试删除共享内存。_shmid 是共享内存的标识符IPC_RMID 是删除共享内存的命令nullptr 是指向 shmid_ds 结构的指针在这个命令中不需要因此传递 nullptr。函数返回的结果存储在 res 变量中。 客户端 #include Shm.hpp #include namedPipe.hppint main() {//1.先创建共享内存Shm shm(gpathname,gproj_id,User);shm.Zero();char *shmaddr (char*)shm.Addr();sleep(3);//2.打开管道NamePiped fifo(comm_path,User);fifo.OpenForWrite();char ch A;while(ch Z){shmaddr[ch-A] ch;ch;std::string temp weakup;std::cout add ch into shm, weakup readerstd::endl;fifo.WriteNamedPipe(temp);sleep(2);}return 0; } 我们创建共享内存并清空原先的数据获取一下共享内存地址然后我们使用之前的管道管道在这里的作用就是同步因为我们的共享内存是直接内存访问这意味着我们的客户端一发送服务端就能看到。所以我们需要借助管道的特性达到同步的效果管道在这里发送什么信息并不重要。 服务端 #include Shm.hpp #include namedPipe.hppint main() {//1.先创建共享内存Shm shm(gpathname,gproj_id,Creater);char *shmaddr (char*)shm.Addr();//2.创建管道NamePiped fifo(comm_path,Creater);fifo.OpenForRead();while(true){std::string temp;fifo.ReadNamedPipe(temp);std::coutshm memory content: shmaddr std::endl;sleep(1);}sleep(5);return 0; } 服务端的逻辑也是一样的不同的是服务端是只读。 代码效果 命名管道与共享内存的区别 命名管道与共享内存是两种常见的进程间通信IPC机制它们各自具有独特的特点和适用场景。以下是两者的主要区别 一、定义与工作原理 命名管道Named Pipe 也称为FIFOFirst In First Out管道。它允许无亲缘关系的进程间进行通信通过一个在文件系统中存在的名字来标识进程可以通过这个名字来访问和通信。数据流动是单向的即数据只能从一个进程流向另一个进程。如果需要双向通信通常需要创建两个管道。命名管道常用于跨进程通信并且允许数据以流的方式从一个进程传输到另一个进程。 共享内存SharedMemory 它是映射一段能被其他进程所访问的内存这段共享内存由一个进程创建但多个进程都可以访问。它是针对其他进程间通信方式运行效率低而专门设计的允许两个或多个进程共享一个给定的存储区。一个进程写入共享内存的信息可以被其他使用这个共享内存的进程通过一个简单的内存读取读出从而实现了进程间的通信。 二、性能与效率 命名管道 数据传输通过内核缓冲区进行存在一定的开销。相比其他IPC机制如信号、消息队列等命名管道的性能处于中等水平。它支持阻塞和非阻塞操作提供了灵活的通信方式。 共享内存 是最快的IPC方式之一因为它允许进程直接访问共享的内存区域减少了数据的拷贝次数。相比命名管道等机制共享内存具有更高的数据传输效率和更低的延迟。但是共享内存需要额外的同步机制如信号量来避免数据竞争和不一致性问题。 三、使用场景与限制 命名管道 适用于需要在不同进程间传递流式数据的场景。由于其半双工特性和需要创建两个管道以实现双向通信的限制命名管道在某些复杂通信场景中可能不够灵活。 共享内存 适用于需要高效数据传输和大量数据共享的场景。由于允许多个进程直接访问同一块内存区域因此需要注意同步和互斥问题以避免数据竞争和访问冲突。 四、实现与操作 命名管道 在类Unix系统中可以通过mkfifo函数创建命名管道并使用open、read、write等系统调用进行读写操作。在Windows系统中命名管道通常通过特定的API进行创建和管理。 共享内存 在类Unix系统中可以使用shmget、shmat、shmdt、shmctl等系统调用进行共享内存的创建、挂接、去关联和控制操作。在Windows系统中也有相应的API用于共享内存的创建和管理。 综上所述命名管道和共享内存是两种各具特色的进程间通信机制。命名管道适用于需要在不同进程间传递流式数据的场景而共享内存则适用于需要高效数据传输和大量数据共享的场景。在选择使用哪种IPC机制时需要根据具体的应用需求和场景进行权衡和选择。
http://www.dnsts.com.cn/news/147804.html

相关文章:

  • 楚雄做网站的公司恒大房地产最新消息
  • 湖南优化网站建设情感营销
  • wordpress站点标题字体建设银行温州分行网站
  • 专题网站建设工作猪八戒logo设计网站
  • 个人做网络推广哪个网站好怎么做网站推广多少钱
  • 计算机网络网站wordpress随机文章小工具
  • 德阳建设局网站宜昌seo优化服务
  • 网站开发公司盈利网上企业登记注册流程
  • 东莞长安网站设计公司模板建站有什么优势
  • 德州做网站的公司上海招标网站
  • wordpress php 版本号贵阳做网站seo
  • 没有网站怎么做淘宝客如何做网上水果网站系统
  • 网站开发挣钱吗漫画app软件定制开发
  • 河北中太建设集团有限公司网站重庆vr制作
  • 注册网站模板施工企业工作分解结构
  • 建设部网站电话wordpress停用react
  • 残联网站建设白酒进货渠道网
  • 哪里找做网站的客户推广网站广告
  • 网站如何导入织梦cms应用制作器
  • 如何为网站做seo体检网站建设过程总结
  • 软件网站建设酒店协会网站集静态模板
  • 网站建设公司教程icp对网站内容
  • 郑州网站哪家好怎样进行站点优化
  • 长春自助建站模板google框架一键安装
  • 网站锚文本链接怎么做腾讯企点怎么删除好友
  • 备案 网站起名新手建什么网站赚钱
  • 大学网页制作与网站建设有没有悬赏做ppt的网站
  • 巅峰网站建设扬州网站建设link5
  • 可信网站认证 服务中心建筑八大员报名官网
  • 有记事本做简易网站手表网站哪个最好知乎