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

义乌网站建设技巧培训网站开发流程的8个步骤

义乌网站建设技巧培训,网站开发流程的8个步骤,网站快照工具,北京市做网站文章目录 1.初识共享内存1.0浅谈System V1.1什么是共享内存#xff1f;1.2Linux-System V共享内存1.3图解共享内存1.4对共享内存的理解 2.创建共享内存2.1共享内存如何创建#xff1f;2.2代码运行与测试2.3shm与pipe的区别2.4shm缺乏访问控制 3.代码理解shm3.1Log.hpp3.2comm… 文章目录 1.初识共享内存1.0浅谈System V1.1什么是共享内存1.2Linux-System V共享内存1.3图解共享内存1.4对共享内存的理解 2.创建共享内存2.1共享内存如何创建2.2代码运行与测试2.3shm与pipe的区别2.4shm缺乏访问控制 3.代码理解shm3.1Log.hpp3.2common.hpp3.3shmServer.cpp3.4shmClient.cpp 1.初识共享内存 1.0浅谈System V 在Linux下一切皆文件的情况下这套模式并不太好。 使用复杂System V的一套接口是OS单独拉出来的一个模块在大项目中不易于集成化需要单独特殊化处理。【但仍与文件有关 】 1.1什么是共享内存 共享内存是Unix系统下的多进程间的通信方法这种方法通常用于一个程序的多进程间通信实际上多个程序间也可以通过共享内存来传递信息。它允许多个不相关的进程访问同一个物理内存区域从而使它们能够相互通信和共享数据。这是进程间通信中最简单的方式之一。 共享内存允许多个进程访问同一块内存就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候其它进程都会察觉到这个更改。这使得共享内存成为进程间共享数据的一种最快的方法。 然而由于多个进程可以同时访问共享内存因此需要某种同步机制如互斥锁和信号量来避免对共享内存的冲突访问。当一个进程正在向共享内存区写数据时其他进程在数据被写入完成前不应该去读或写这些数据。 共享内存的使用通常包括以下步骤 创建或打开共享内存对象。 将指定的共享内存映射到进程的地址空间以便进行访问。 在完成通信后撤销对共享内存的映射。 删除共享内存对象。 需要注意的是共享内存是在多个进程之间共享一段内存区域因此对于这段内存的访问和管理需要谨慎处理以避免出现数据不一致或冲突的情况。 总的来说共享内存是一种高效的进程间通信方式它允许多个进程直接读写同一块内存区域而不需要进行数据的拷贝从而大大提高了通信的效率。但是它也需要适当的同步机制来确保对共享内存的正确访问。 1.2Linux-System V共享内存 Linux下的System V共享内存是Unix系统V版本引入的一种进程间通信IPC机制。它允许多个进程共享同一块物理内存区域以实现高效的数据交换和通信。 在System V共享内存中进程通过系统调用如shmget、shmat、shmdt等来创建、映射和解除映射共享内存段。这些系统调用提供了对共享内存的管理和操作功能。 具体来说shmget函数用于创建或获取一个共享内存段的标识符。它需要提供一个唯一的键值key来标识共享内存段并指定共享内存的大小和访问权限。成功时shmget返回一个共享内存标识符shmid失败时返回-1。 shmat函数用于将共享内存段映射到进程的地址空间中。它接受共享内存标识符shmid和可选的映射地址作为参数。如果映射地址为空则系统会自动选择一个合适的地址进行映射。成功时shmat返回映射后的地址失败时返回-1。 一旦共享内存映射到进程的地址空间多个进程就可以通过直接读写这块内存区域来进行通信。由于共享内存是直接在物理内存中分配的因此它的访问速度非常快是进程间通信中最快的方式之一。 需要注意的是多个进程同时访问共享内存时可能会出现数据竞争和不一致的问题。因此需要使用同步机制如信号量来确保对共享内存的正确访问。 当不再需要共享内存时可以使用shmdt函数来解除映射并使用shmctl函数来删除共享内存段。这些操作可以确保资源被正确释放避免内存泄漏和不必要的资源浪费。 总的来说Linux下的System V共享内存是一种高效的进程间通信机制它允许多个进程直接读写同一块内存区域而不需要进行数据的拷贝和传输。然而由于共享内存访问的复杂性需要谨慎处理同步和并发访问的问题。 1.3图解共享内存 共享内存和动态库都被映射到进程地址空间的共享区 通信原理图 1.4对共享内存的理解 共享内存提供者是操作系统操作系统要管理共享内存 先描述在组织共享内存 共享内存块 共享内存的内核数据结构对共享内存的管理转变成对数据结构的增删查改 OS怎么知道 如何知道是否需要释放这块内存时当前有多少进程和共享内存关联这块内存有多大如何禁止一些进程访问这块内存权限问题 需要知道该内存的一系列属性信息 ⇒ 通过内核数据结构获取属性信息 2.创建共享内存 共享内存是有很多个的 类似于这样 2.1共享内存如何创建 假设A进程server与B进程client通信 A进程调用shmget()接口 返回值 共享内存的用户层标识符类似fd但不同 key 通过调用ftok() 获取的系统中唯一的一个值数值是几不重要只要唯一即可–用来唯一标识指定共享内存块的A创建了共享内存块B怎么看到这个共享内存块如何保证二者可以访问同一块资源呢AB通过唯一的key在内核中访问同一个共享内存块 ⇒ 看到了同一块“资源”AB如何获取同一个keyAB调用同一个ftok()根据相同的参数通过某种算法计算出同一个key这个经过算法加算出来的key一般在内核中是唯一的存在出错的情况此处不讨论A调用ftok()获取一个key在内存中创建一个共享内存块以此key标识这个shm将此key存入该shm的数据结构中B通过ftok()相同的参数相同的算法获取相同的key根据这个key去内核中寻找对应的shm至此AB两个进程看到了同一块“资源” size 创建的shm的大小 共享内存的大小 最好是页(PAGE: 4096)的整数倍 4kb OS管理物理内存时 page的大小以4kb为单位 若申请4097 OS会开辟2个page【对page向上取整】 而第二个page的4095 申请shm的人无法使用 OS其他进程也无法使用 大大的浪费/zz行为 shmflg 一般有两个选项 IPC_CREAT单独使用创建shm时若底层已经存在想要创建的shm获取并返回shmid若不存在创建并返回shmid IPC_EXCL单独使用无意义 IPC_CREAT and IPC_EXCL若底层不存在创建并返回shmid若底层存在想要创建的shm出错返回。⇒ 只要返回成功此时使用的一定是一个全新的shm ftok() shmctl 建立/删除映射 shmid要将哪个共享内存建立映射 shmaddr要建立映射的虚拟地址 不建议指定 传空指针让OS帮我们建立映射 shmflg可以传参以只读方式挂接等 shmid: 这是一个共享内存标识符通常是通过 shmget 函数获得的。 nullptr: 这是一个指向 shmat 应该放置附加内存的起始地址的指针。由于这里传入的是 nullptr内核将自动选择一个合适的地址。 0: 这是一个标志位用于控制共享内存的访问权限和附加方式。在这里0 表示使用默认的读/写权限。 返回值 shmaddr: 这是一个指向附加的共享内存段的指针。如果 shmat 调用成功shmaddr 将指向共享内存段的起始地址。如果调用失败shmaddr 将是 (char *) -1并且 errno 将被设置为指示错误原因的值。 注意在实际代码中你应该检查 shmaddr 是否为 (char *) -1 来确定 shmat 调用是否成功并相应地处理任何错误。 另外请注意shmat 的返回值类型是 void*但在这个例子中它被强制转换为 char*。这样做是为了方便进行指针算术和内存访问因为 char 类型的大小是 1 字节所以 char* 指针可以逐字节地遍历内存。 与malloc的使用类似 int shmid shmget(k, SHM_SIZE, 0); shmget 是一个在 Unix 和类 Unix 系统如 Linux中用于创建或获取共享内存段的系统调用。共享内存是多个进程间通信的一种方式允许多个进程共享同一块内存区域。 k: 这是共享内存段的键key。通常这是一个整数用于唯一标识共享内存段。如果键的值为 IPC_PRIVATE那么将创建一个新的、唯一的共享内存段。 SHM_SIZE: 这是你希望创建的共享内存段的大小以字节为单位。如果共享内存段已经存在这个值将被忽略但通常你会希望它与你期望的大小相匹配。 第三个参数是共享内存段的权限标志。当你传递 0 作为这个参数时你实际上没有指定任何权限标志。那么函数将尝试获取一个已经存在的共享内存段并且不会检查或修改其权限。 函数的返回值 shmid 是一个整数代表共享内存段的标识符。如果函数成功它将返回这个标识符如果失败它将返回 -1。 int shmid shmget(k, SHM_SIZE, 0); 这行代码尝试获取一个与键 k 关联的共享内存段如果它不存在并且没有 IPC_CREAT 标志则调用将失败。返回的标识符如果成功将存储在 shmid 变量中。 shmid vs key shmid: 用户层标定shm唯一性 key内核层面上唯一标识shm的 只创建时用key大多数情况用户访问shm用shmid 【匿名/命名管道等基于文件的生命周期随进程】 当进程结束shm还在吗 若不显示删除sm仍然存在System V shm生命周期随内核。 怎么删命令行命令删/代码调用接口删建议第二种 2.2代码运行与测试 while : ; do ipcs -m ; sleep 1 ; done 物理内存中的shm映射到进程地址空间后进程地址空间的shm属于内核空间还是用户空间 映射到虚拟地址空间的shm属于用户空间当AB两个进程将同一个物理内存的shm映射到各自的PASProcess Address SpaceAB进程通信时直接进行内存级的读写即可无需经过其他调用。 匿名管道/命名管道中的pipe/fifo为什么要通过调用系统接口read/write来进行通信 pipe/fifo都是文件是OS进行维护和管理的而映射到PAS的shm相当于一个进程的 以上的工作创建key/创建shm/映射shm/删除映射/删除shm是在干嘛 让不同的进程看到同一份“资源”内存 2.3shm与pipe的区别 shm在通信方法中速度较快 pipe的通信方式 shm的通信方式 2.4shm缺乏访问控制 只要是通信双方使用shm一方直接向共享内存中写入数据另一方就可以立马看到对方写入的数据。 共享内存是所有进程间通信(IPC)速度最快的不需要过多的拷贝不需要将数据给操作系统共享内存缺乏访问控制 会带来并发问题 缺乏访问控制导致写入方写了一部分数据 读取方就读走了并对这半个数据进行了处理得到了错误的结果 写入方不在/写入方不写 读取方仍在读 双方压根不知道对方的存在 即写入方只知道一味的写 读取方只知道一味的读 3.代码理解shm 3.1Log.hpp #ifndef _LOG_H_ #define _LOG_H_#include iostream #include ctime#define Debug 0 #define Notice 1 #define Warning 2 #define Error 3const std::string tip[] {Debug,Notice,Warning,Error};std::ostream Log(std::string message, int option) {// 获取时间戳 time_t timestamp; time(timestamp);time_t timestamp time(nullptr);if (timestamp std::time_t(-1)){std::cerr 获取时间失败 std::endl;exit(1);}// 获取格式化时间 tm *localtime(const time_t *__timer)tm *timeinfo std::localtime(timestamp);std::cout | 1900 timeinfo-tm_year - 1 timeinfo-tm_mon - timeinfo-tm_mday timeinfo-tm_hour : timeinfo-tm_min : timeinfo-tm_sec | tip[option] | message;return std::cout; }#endif3.2common.hpp #pragma once#include iostream #include cstdio #include cstring #include unistd.h #include sys/types.h #include sys/ipc.h #include sys/shm.h #include cassert #include sys/stat.h #include fcntl.h #include Log.hppusing namespace std; // 实际项目中 不展开#define PATH_NAME /home/lhr/linux // 此路径一定要有访问权限 #define PROJ_ID 0x66 // 0~255 #define SHM_SIZE 4096 // 共享内存的大小 最好是页(PAGE: 4096)的整数倍 4kb #define FIFO_NAME ./fifo // 当前路径下创建一个fifo管道文件string ConvertToHex(key_t k) {char buffer[32];snprintf(buffer, sizeof buffer, 0x%x, k);return buffer; }class Init { public:Init(){umask(0);int n mkfifo(FIFO_NAME, 0666);assert(n 0);(void)n;Log(create fifo success, Notice) std::endl;}~Init(){unlink(FIFO_NAME);Log(remove fifo success, Notice) std::endl;} };#define READ O_RDONLY #define WRITE O_WRONLYint OpenFIFO(std::string pathname, int flags) {int fd open(pathname.c_str(), flags);assert(fd 0);return fd; }//服务端调用read去阻塞等待数据 直到有人向管道写数据 等待停止 void Wait(int fd) {//no_use仅仅是实现“读数据”这一动作的对象 其中的数据无意义Log(等待中...., Notice) std::endl;//read接口从fd读存到tmp 无数据则阻塞等待uint32_t no_use 0;ssize_t s read(fd, no_use, sizeof(uint32_t));assert(s sizeof(uint32_t));(void)s; }//客户端调用write向管道写数据 此动作使得管道中添加数据 服务端停止等待 void Wake(int fd) {//no_use仅仅是实现“写数据”这一动作的对象 其中的数据无意义uint32_t no_use 1;ssize_t s write(fd, no_use, sizeof(uint32_t));assert(s sizeof(uint32_t));(void)s;Log(唤醒中...., Notice) std::endl; }void CloseFifo(int fd) {close(fd); }3.3shmServer.cpp #include common.hpp// 程序加载时自动构建全局对象 -- 调用构造函数创建管道文件 // 程序退出时自动析构全局对象 -- 调用析构函数删除管道文件 Init init;int main() {// 1. 创建公共的Key值key_t k ftok(PATH_NAME, PROJ_ID);assert(k ! -1);Log(create key done, Debug) server key : ConvertToHex(k) endl;// 2. 创建shm shm创建成功后会自动全部置0// server是通信的发起者 建议创建一个全新的共享内存int shmid shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);if (shmid -1){perror(shmget);exit(1);}Log(create shm done, Debug) shmid : shmid endl;//sleep(10);// 3. 将指定的共享内存 挂接到自己的地址空间char *shmaddr (char *)shmat(shmid, nullptr, 0);Log(attach shm done, Debug) shmid : shmid endl;//sleep(10);// 开始进行通信 将共享内存看成一个大字符串 char buffer[SHM_SIZE];int fd OpenFIFO(FIFO_NAME, READ);while (true){Wait(fd);// 临界区printf(%s\n, shmaddr);if (strcmp(shmaddr, quit) 0)break;}CloseFifo(fd);// 4. 将指定的共享内存 从自己的地址空间中删除映射int n shmdt(shmaddr);assert(n ! -1);(void)n;Log(detach shm done, Debug) shmid : shmid endl;//sleep(10);// 5. 删除共享内存 IPC_RMID: 即便是有进程和当下的shm挂接 依旧删除共享内存n shmctl(shmid, IPC_RMID, nullptr);assert(n ! -1);(void)n;Log(delete shm done, Debug) shmid : shmid endl;return 0; }3.4shmClient.cpp #include common.hppint main() {Log(Client pid is : , Debug) getpid() endl;// 创建公共的Key值key_t k ftok(PATH_NAME, PROJ_ID); // typedef int key_tif (k 0){Log(create key failed, Error) client key : ConvertToHex(k) endl;exit(1);}Log(create key done, Debug) client key : ConvertToHex(k) endl;// 获取共享内存int shmid shmget(k, SHM_SIZE, 0);if (shmid 0){Log(obtain shm failed, Error) shmid : shmid endl;exit(2);}Log(obtain shm success, Debug) shmid : shmid endl;//sleep(10);// 将指定的共享内存 挂接到自己的地址空间char *shmaddr (char *)shmat(shmid, nullptr, 0);if (shmaddr nullptr){Log(attach shm failed, Error) shmid : shmid endl;exit(3);}Log(attach shm success, Debug) shmid : shmid endl;//sleep(10);// 开始通信 client将共享内存看做一个char 类型的bufferint fd OpenFIFO(FIFO_NAME, WRITE);while (true){ssize_t s read(0, shmaddr, SHM_SIZE - 1); // 从stdin读数据存到shmif (s 0){shmaddr[s - 1] 0; // abcd\n abcd0Wake(fd);if (strcmp(shmaddr, quit) 0)break;}}CloseFifo(fd);/* 每一次都向共享内存的起始地址写入char *msg hello server, Im Client. my pid: %d, inc: %c\n;for (char a a; a z; a){shmaddr[a - a] a; // 直接当成字符数组来看待snprintf(shmaddr, SHM_SIZE - 1, msg, getpid(), a); // 库函数格式化输入数据sleep(1);}strcpy(shmaddr, quit);*/// 删除映射int n shmdt(shmaddr);assert(n ! -1);(void)n;Log(detach shm success, Debug) shmid : shmid endl;//sleep(10);// client不需要chmctl删除return 0; }
http://www.tj-hxxt.cn/news/218674.html

相关文章:

  • 网站托管工作室郑州专业做网站公司
  • jsp网站开发案例建设项目环保竣工验收备案网站
  • 网络营销模式的建议北京优化推广
  • 南通网站推广公司建设牌安全带官方网站
  • 手机自助建站平台国外做电商网站
  • 网站建设外包注意什么福田祥菱m2柴油版
  • 二级网站怎么建网站不备案可以访问吗
  • 国外高大上设计网站临沂网站建设昂牛网络
  • 建筑设计公司名称起名网站站seo教程
  • 惠州网站制作策划网络服务提供者接到权利人的通知后
  • 免费二级网站星辰wordpress主题
  • 赣州市开发区建设局网站山东省建设管理局网站
  • 枣强网站建设代理京东云免费建wordpress
  • 网站结构分析怎么写做一个公司的网站应做哪些准备工作
  • 电子商务网站例网站建设小程序湖南
  • 好的学习网站打广告个人站长和企业网站
  • 创建企业网站经过哪些步骤网站建设属于什么会计科目
  • 珠海找工作哪个网站好wordpress自适应 分页
  • 什么语言开发网站建立网站赚钱 优帮云
  • 怎样在门户网站做 推广门户网站建设管理工作的意见
  • phpcms 中英文网站同城版网站建设
  • 更新网站要怎么做呢广州高端模板网站
  • 免费建站微信wordpress设置了固定连接打不开
  • 住房城乡建设网站wordpress添加面包屑导航
  • 网站开发有哪些服务器个人网站可以做淘宝客
  • 做网站时随便弄上去的文章怎么删掉网页设计与制作轮播图教程
  • 网站地图怎么使用wordpress vs php的区别
  • 家居企业网站建设如何西安手机网站制作
  • 手机网站cms 开源太原关键词排名优化
  • 免费开发网站徐州百姓网发布信息