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

苹果手机软件开发工具百度seo网站优化

苹果手机软件开发工具,百度seo网站优化,深圳市涂能装饰设计公司网站,字画网站模板目录 共享内存的挂接与取消挂接 sharememoty.hpp编写 server.cc / clent.cc /测试 IPC通信 使用命名管道保护 我们今天学习共享内存的通信!!! 共享内存的挂接与取消挂接 我们之前创建了共享内存,但是没有和进程想关联&…

目录

共享内存的挂接与取消挂接

sharememoty.hpp编写

server.cc / clent.cc /测试

IPC通信

使用命名管道保护


我们今天学习共享内存的通信!!!

共享内存的挂接与取消挂接

我们之前创建了共享内存,但是没有和进程想关联,没有关联进程这么调度,所以我们需要映射挂接到自己的目录,使用shmat()函数实现挂接:

三个参数,第一个就是shmget的返回值也就是ID,第二个参数是本地的虚拟地址,一般不需要自己设置,第三个参数一般设置为0,详情见上面。

取消挂接我们使用shmdt()函数,shmdt(Shared Memory Detach)是 System V 共享内存(Shared Memory)机制中的一个函数,用于将共享内存段从当前进程的地址空间分离(取消映射)。

一个参数就是shmat成功的返回值。

然后运行server并监视共享内存看结果:

咦,这么什么都没有,nattch这么还是0,不是应该有依赖了吗,重点不再nattch,这个perms这么也是0,在 ipcs 命令的输出中,perms 代表 IPC 资源的权限(Permissions),用于控制进程对共享内存、信号量或消息队列的访问权限。哦我们没有设置共享内存的权限导致的。

我们可以在创建共享内存的时候进行创建,shmflg可以设置权限如下:

设置为仅自己可读写,然后所有进程可见。

可以看到正常挂接并且解除了,我们回过头来看操作系统,挂接就需要虚拟地址申请空间,操作系统申请空间是按照块为单位申请的,要么4KB,2KB等等,假设我们的系统每次申请空间是4KB,4096个字节,那如果我们今天的共享内存设置成4098,那操作系统是不是需要申请8kb才可以装下,bytes下面应该是8kb。但是操作系统不会故意迎合人的思维和行为而创建,操作系统实际上是创建了8kb没错,但是仍然会显示4098做为实际占有,你在 ipcs -m 里看到的共享内存大小 不是你创建时指定的大小,而是操作系统按页对齐后的实际分配大小

那我们挂接完了就剩下通信了,但是目前这么写代码有点难看呀!,我们需要进行封装,为了使接口共享出来,我们将comm.hpp改为sharememory.hpp,作为共享空间,将一些公共的代码共享出来。如下:

sharememoty.hpp编写

具体框架如上,不用我过多解释了吧,清楚明了了。接着填写进去就可以了。值得注意的是,这个getshm也是获取shmid,但是里面的shmflg的选项不能含有IPC_EXCL,因为这个函数是获取已有的共享内存的shmid。

class sharememory
{
public:sharememory();~sharememory();// 创建shmint creatshm(){umask(0);key_t k = ::ftok(path.c_str(), projid);if (k < 0){cerr << "ftok fail!" << endl;return -1;}cout << "k: " << k << endl;// 创建共享内存int shmid = ::shmget(k, gshmsize, IPC_CREAT | IPC_EXCL | gmode);if (shmid < 0){cerr << "shmget error" << endl;return -2;}cout << "shmid: " << shmid << endl;return shmid;}// 得到shm,已有的获取不创建int getshm(){key_t k = ::ftok(path.c_str(), projid);if (k < 0){cerr << "ftok fail!" << endl;return -1;}cout << "k: " << k << endl;// 创建共享内存int shmid = ::shmget(k, gshmsize, IPC_CREAT | gmode);if (shmid < 0){cerr << "shmget error" << endl;return -2;}cout << "shmid: " << shmid << endl;return shmid;}// 挂接本地地址void *attachshm(int shmid){void* ret = shmat(shmid, nullptr, 0);if ((long long)ret == -1){return nullptr;}cout << "attach done" << (long long)ret << endl;return ret;}// 解除映射void detachshm(void* ret){::shmdt(ret);cout << "detach done: " << (long long)ret << endl;}// 删除shmvoid deleteshm(int shmid){shmctl(shmid, IPC_RMID, nullptr);}
};

我们看到创建shmid和得到的函数高度一致,所以我们可以将其设置为私有函数,然后再调用,放在冗余。然后shmflg部分完全可以由用户自己传递。注意参数传递的不一致!!!

class sharememory
{
private:int creatshmhelper(int shmflg){umask(0);key_t k = ::ftok(path.c_str(), projid);if (k < 0){cerr << "ftok fail!" << endl;return -1;}cout << "k: " << k << endl;// 创建共享内存int shmid = ::shmget(k, gshmsize, shmflg);if (shmid < 0){cerr << "shmget error" << endl;return -2;}cout << "shmid: " << shmid << endl;return shmid;}
public:sharememory();~sharememory();// 创建shmint creatshm(){return creatshmhelper(IPC_CREAT | IPC_EXCL | gmode);}// 得到shm,已有的获取不创建int getshm(){return creatshmhelper(IPC_CREAT | gmode);}// 挂接本地地址

接着测试是否挂接->取消挂接->删除shm的过程是否成功:

server.cc和clent中都遵循:创建/获取shmid,挂接,解除挂接,删除的规则,当然删除只需要创建的一方就可以了,我们这里选择server。在此之前被忘了对sharememory进行初始化对象。

server.cc / clent.cc /测试

接下来测试:

我们还可以进一步的进行改进,可以注意到一些如k等的值是可以放在类里面进行管理的,这样server和clent都可以直接看到并且都有一份。

我们仅仅放置 _shmid(共享内存id),key(k值),_addr(映射地址)作为私有。如下修改减少了return的必要。

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/stat.h>
using namespace std;
const string path = "/home/yulin2/linuxtest";
int projid = 0x6666;
int gshmsize = 4098;
mode_t gmode = 0600;
class sharememory
{
private:int creatshmhelper(int shmflg){//umask(0);_key = ::ftok(path.c_str(), projid);if (_key < 0){cerr << "ftok fail!" << endl;return -1;}cout << "k: " << _key << endl;// 创建共享内存_shmid = ::shmget(_key, gshmsize, shmflg);if (_shmid < 0){cerr << "shmget error" << endl;return -2;}cout << "shmid: " << _shmid << endl;return _shmid;}
public:sharememory():_shmid(-1),_key(-1),_addr(nullptr){}~sharememory(){}// 创建shmvoid creatshm(){creatshmhelper(IPC_CREAT | IPC_EXCL | gmode);}// 得到shm,已有的获取不创建void getshm(){creatshmhelper(IPC_CREAT | gmode);}// 挂接本地地址void attachshm(){_addr = shmat(_shmid, nullptr, 0);if ((long long)_addr == -1){cout << "attach error" << endl;}cout << "attach done" << (long long)_addr << endl;}// 解除映射void detachshm(){if (_addr != nullptr)::shmdt( _addr);cout << "detach done: " << (long long) _addr << endl;}// 删除shmvoid deleteshm(){shmctl(_shmid, IPC_RMID, nullptr);}//打印属性void shmmeta(){}
private:int _shmid;key_t _key;void *_addr;
};sharememory shm;

这个打印属性的函数在当前没有实现的必要。对应的.cc也要进行修改:

我就不监视了,毕竟肯定会看到nattch等于2的。

经过我们如上一堆骚操作,只是将框架搭好了,我们还没有开始通信呢,我们现在就开始:

IPC通信

我们直接选择在.cc中进行通信,我们首先要拿得到挂接的虚拟地址,所以我们添加函数getaddr,我们直接向这个地址内写入就可以了,因为这个地址相当于共享内存,因为我们挂接了的。字符串名字就是这个首地址,所以这个地址我们可以理解为字符串,当然我们也可以把它当成结构体等等。C++打印char* 相当于打印这个指针指向的字符串

 

我们直接在server里面打印这个字符串(那个指针),然后在clent里面写入这个空间,看结果。

#include"sharememory.hpp"
int main()
{shm.creatshm();shm.attachshm();//sleep(10);cout << "server attach done" << endl;//进行IPCchar* strinfo = (char*)shm.getaddr();while(true){printf("%s\n", strinfo);sleep(1);}shm.detachshm();cout << "server detach done" << endl;//sleep(10);shm.deleteshm();cout << "detel shm" << endl;return 0;
}
#include"sharememory.hpp"
int main()
{shm.getshm();shm.attachshm();//sleep(10);cout << "clent attach done" << endl;char* strinfo = (char*)shm.getaddr();char ch = 'A';while(ch <= 'Z'){sleep(3);strinfo[ch - 'A'] = ch;ch++;}shm.detachshm();cout << "clent detach done" << endl;return 0;
}

我们可以看到当我们只打开读端时,server并没有像管道那样没有东西可读就停止,而是直接读空,当clent以三秒一次写入时,读端确实读了,但是没有去重呀,可见共享内存的读取是不等写进程了自我独立运行的,是让两个进程各自共享用户空间内存块,当我们关闭读端时,写端还在写入,反之也是类似的,所以没有加任何保护机制,这个很危险的,这种让进程具有独立性的方法,容易让两进程数据不一致(一端还在写,一端已经读取了),我们就需要对共享内存自己完成保护,我们一般使用加锁,或者使用数据量保护处于临界区的临界资源。基于管道的性质,我们还可以使用命名管道进行保护!!!但是这种方法也是有风险的,所以加锁最好!!!

共享内存不需要系统级的文件操作而是直接写入,所以这就意味着写入共享内存不存在文件缓冲区,所以通信速度最快。进程是直接看到映射的共享内存,所以不需要文件操作。

使用命名管道保护

写端在循环写入共享内存的同时先写入命名管道,等单次写入命名管道完成时,再提醒读端读取同时读取共享内存的内容,所以读端先访问管道,这是单向的,如果要完成双向的通信就需要两个命名管道。

命名管道在此的作用就是提醒读取的作用,等单次写入完成了再读,没有数据就不要读取,但是这样还是没有避免重复读取,只是避免了读取写入不一致,本质还是要到共享内存读的。命名管道(FIFO)在这里的作用更像是一个通知机制,用于同步写入和读取的时机,而真正的数据还是存放在共享内存(Shared Memory, SHM)中。解决共享内存的数据一致性问题,还是必须考虑加锁。如果多个进程可能同时访问共享内存,就需要同步机制来确保数据的正确性。常见的同步手段包括互斥锁(mutex)、读写锁、信号量等。

http://www.dtcms.com/wzjs/256672.html

相关文章:

  • 个人特种作业证查询小红书seo软件
  • 合肥百度快照优化排名郑州seo顾问
  • 国内金融行业网站开发快速排名优化推广价格
  • 网站建设授权书适合30岁短期培训班
  • 企业推广是什么职业seo网站关键词排名快速
  • 厦门做企业网站的公司网站建设的推广渠道
  • 写作网站设定线下推广
  • 天津网站制作百度指数怎么算
  • 开发一款软件的费用三明网站seo
  • 国外注册机网站软文发布平台媒体
  • 检测网站是否被做跳转世界足球排名最新
  • b2c所有网站在线一键生成网页
  • 珠海商城网站建设网站查询系统
  • 河南省建设厅证件查询官网百度关键词优化怎么做
  • 什么语言做网站最好短视频推广公司
  • 网站被挂黑链怎么删除排行榜
  • 溧阳网站开发创建自己的网站怎么弄
  • 我想做自己网站怎么做百度极速版免费下载
  • 万户网络的网站安全吗线上线下整合营销方案
  • 服装网站建设项目实施报告范文搭建一个网站需要多少钱?
  • 网站开发的选题意义及背景社会新闻最新消息
  • 专做定制网站建设搜狗营销
  • 网站做赌博词怎么推广百度视频免费下载
  • 零基础源码建设网站seo薪酬
  • 行业门户网站开发简单网页设计模板html
  • 做网站需要空间跟域名吗竞价外包推广
  • 北京网站建设 优化seo教程自学网
  • 访问自己做的网站网站优化有哪些技巧
  • 尊园地产做的网站百度seo怎么优化
  • 自建站英文济南网站制作