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

做网站的销售好做吗dw软件怎么用

做网站的销售好做吗,dw软件怎么用,网站建设技术教程,古风网站建设模板下载进程间通信介绍 进程间通信目的 数据传输#xff1a;一个进程需要将它的数据发送给另一个进程资源共享#xff1a;多个进程之间共享同样的资源通知事件#xff1a;一个进程需要向另一个或一组进程发送消息。通知它#xff08;它们#xff09;发生了某种事件#xff08;如…进程间通信介绍 进程间通信目的 数据传输一个进程需要将它的数据发送给另一个进程资源共享多个进程之间共享同样的资源通知事件一个进程需要向另一个或一组进程发送消息。通知它它们发生了某种事件如进程终止时要通知父进程。进程控制有些进程希望完全控制另一个进程的执行如Debug进程此时控制进程希望能够拦截另一个进程的所有陷入和异常并能够即是知道它的状态改变。 进程间通信发展 管道 匿名管道pipe命名管道 system V IPC System V 消息队列System V 共享内存System V 信号量 POSIX IPC 消息队列共享内存信号量互斥量条件变量读写锁 管道 什么是管道 管道是Unix中最古老的进程间通信 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。 匿名管道 mypipe.cc #includeiostream #includeunistd.h #includecerrno #includestring.h #includeassert.h #includeunistd.hint main() {//让不同的进程看到同一份资源//任何一种进程间通信中一定要先保证不同的进程之间看到同一份资源int pipefd[2] {0};//1、创建管道int n pipe(pipefd);if(n0){std::coutpipe errorerrno: strerror(errno)std::endl;return 1;}std::coutpipefd[0]:pipefd[0]std::endl;//读端 -嘴巴-读书std::coutpipefd[1]:pipefd[1]std::endl;//写端 -笔-写 //2、创建子进程pid_t id fork();assert(id!-1);//正常应该用判断这里就直接断言了意外之外用if意料之内用assertif(id 0)//子进程{//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[0]);//4、开始通信--结合某种场景const std::string namestrhello 我是子进程;int cnt 1;char buffer[1024];while(true){snprintf(buffer,sizeof(buffer),%s,计数器%d,我的id,%d,namestr.c_str(),cnt,getpid());write(pipefd[1],buffer,strlen(buffer));sleep(1);}close(pipefd[1]);exit(0);}//父进程//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[1]);//4、开始通信--结合某种场景char buffer[1024] ;while(true){sleep(1);int n read(pipefd[0],buffer,sizeof(buffer));if(n0){buffer[n]\0;std::cout我是父进程child give me message: bufferstd::endl;}}return 0; }Makefile mypipe:mypipe.ccg -o $ $^ -stdc11 .PHONY:clean clean:rm -rf mypipe运行结果 可以看到父进程读到了子进程中的内容同时父进程读取的速度和写入的速度是相同的。 管道的特点 单向通信管道的本质是文件因为fd的生命周期随进程管道的生命周期是随进程的。管道通信通常用来进行具有“血缘”关系的进程进行程序间通信常用于父子通信–pipe打开管道并不清楚管道的名字叫做匿名管道。在管道通信中写入的次数和读取的次数不是严格匹配的读写次数的多少没有强相关–表现–字节流 4种场景 如果我们read读取完毕了所有的管道数据如果对方不发我就只能等待。如果我们write端将管写满了我们就不能继续写了。 #includeiostream #includeunistd.h #includecerrno #includestring.h #includeassert.h #includeunistd.hint main() {//让不同的进程看到同一份资源//任何一种近侧和你关键通信中一定要先保证不同的进程之间看到同一份资源int pipefd[2] {0};//1、创建管道int n pipe(pipefd);if(n0){std::coutpipe errorerrno: strerror(errno)std::endl;return 1;}std::coutpipefd[0]:pipefd[0]std::endl;//读端 -嘴巴-读书std::coutpipefd[1]:pipefd[1]std::endl;//写端 -笔-写 //2、创建子进程pid_t id fork();assert(id!-1);//正常应该用判断这里就直接断言了意外之外用if意料之内用assertif(id 0)//子进程{//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[0]);//4、开始通信--结合某种场景// const std::string namestrhello 我是子进程;// int cnt 1;// char buffer[1024];int cnt 0;while(true){// snprintf(buffer,sizeof(buffer),%s,计数器%d,我的id,%d,namestr.c_str(),cnt,getpid());// write(pipefd[1],buffer,strlen(buffer));//sleep(1);char x X;write(pipefd[1],x,1);std::coutcnt:cntstd::endl;}close(pipefd[1]);exit(0);}//父进程//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[1]);//4、开始通信--结合某种场景char buffer[1024] ;while(true){sleep(1);int n read(pipefd[0],buffer,sizeof(buffer));if(n0){buffer[n]\0;std::cout我是父进程child give me message: bufferstd::endl;}}return 0; }运行结果 3. 如果我们关闭了写端读取完毕管道数据再读就会read返回0表明读到了文件结尾。 #includeiostream #includeunistd.h #includecerrno #includestring.h #includeassert.h #includeunistd.h #includesys/wait.hint main() {//让不同的进程看到同一份资源//任何一种近侧和你关键通信中一定要先保证不同的进程之间看到同一份资源int pipefd[2] {0};//1、创建管道int n pipe(pipefd);if(n0){std::coutpipe errorerrno: strerror(errno)std::endl;return 1;}std::coutpipefd[0]:pipefd[0]std::endl;//读端 -嘴巴-读书std::coutpipefd[1]:pipefd[1]std::endl;//写端 -笔-写 //2、创建子进程pid_t id fork();assert(id!-1);//正常应该用判断这里就直接断言了意外之外用if意料之内用assertif(id 0)//子进程{//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[0]);//4、开始通信--结合某种场景// const std::string namestrhello 我是子进程;// int cnt 1;// char buffer[1024];int cnt 0;while(true){// snprintf(buffer,sizeof(buffer),%s,计数器%d,我的id,%d,namestr.c_str(),cnt,getpid());// write(pipefd[1],buffer,strlen(buffer));//sleep(1);char x X;write(pipefd[1],x,1);std::coutcnt:cntstd::endl;sleep(1);break;}close(pipefd[1]);exit(0);}//父进程//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[1]);//4、开始通信--结合某种场景char buffer[1024] ;int cnt 0;while(true){int n read(pipefd[0],buffer,sizeof(buffer)-1);if(n0){buffer[n]\0;std::cout我是父进程child give me message: bufferstd::endl;}else if(n0){std::cout我是父进程读到了文件结尾std::endl;break;}else{std::cout我是父进程读异常了std::endl;break;}sleep(1);if(cnt5) break;}close(pipefd[0]);int status 0;waitpid(id,status,0);std::coutsig:(status 0x7F)std::endl;//sleep(100);return 0; }运行结果 如果写端一直写读端关闭会发生什么呢没有意义操作系统不会维护无意义、低效率或者浪费资源的事情。OS会杀死一直在写入的进程OS会通过信号来终止进程。13SIGPIPE #includeiostream #includeunistd.h #includecerrno #includestring.h #includeassert.h #includeunistd.h #includesys/wait.hint main() {//让不同的进程看到同一份资源//任何一种近侧和你关键通信中一定要先保证不同的进程之间看到同一份资源int pipefd[2] {0};//1、创建管道int n pipe(pipefd);if(n0){std::coutpipe errorerrno: strerror(errno)std::endl;return 1;}std::coutpipefd[0]:pipefd[0]std::endl;//读端 -嘴巴-读书std::coutpipefd[1]:pipefd[1]std::endl;//写端 -笔-写 //2、创建子进程pid_t id fork();assert(id!-1);//正常应该用判断这里就直接断言了意外之外用if意料之内用assertif(id 0)//子进程{//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[0]);//4、开始通信--结合某种场景// const std::string namestrhello 我是子进程;// int cnt 1;// char buffer[1024];int cnt 0;while(true){// snprintf(buffer,sizeof(buffer),%s,计数器%d,我的id,%d,namestr.c_str(),cnt,getpid());// write(pipefd[1],buffer,strlen(buffer));//sleep(1);char x X;write(pipefd[1],x,1);std::coutcnt:cntstd::endl;sleep(1);//break;}close(pipefd[1]);exit(0);}//父进程//3、关闭不需要的fd,让父进程去读子进程去写close(pipefd[1]);//4、开始通信--结合某种场景char buffer[1024] ;int cnt 0;while(true){int n read(pipefd[0],buffer,sizeof(buffer)-1);if(n0){buffer[n]\0;std::cout我是父进程child give me message: bufferstd::endl;}else if(n0){std::cout我是父进程读到了文件结尾std::endl;break;}else{std::cout我是父进程读异常了std::endl;break;}sleep(1);if(cnt5) break;}close(pipefd[0]);int status 0;waitpid(id,status,0);std::coutsig:(status 0x7F)std::endl;sleep(100);return 0; }运行结果 可以看到子进程退出后由父进程通过waitpid读到子进程退出码。 管道特点 只能用于具有共同祖先的进程具有亲缘关系的进程之间进行通信通常一个管道由一个进程创建然后该进程调用fork此后父子进程之间就可应用该管道。管道提供流式服务。一般而言进程退出管道释放所以管道的生命周期随进程。一般而言内核会对管道操作进行同步与互斥。管道是半双工的数据只能向一个方向流动需要双方通信时需要建立起两个管道。 命名管道 管道应用的一个限制就是只能再基友共同祖先具有亲缘关系的进程间通信。如果我们想不在不相关的进程之间交换数据可以使用FIFO文件来做这项工作它被称为命名管道。命名管道是一种特殊类型的文件。 创建一个命名管道 命名管道可以从命令行上创建命令行方式是使用下面这个方式。 mkfifo filename命名管道也可以从程序里面创建相关函数有 int mkfifo(const char *filename,mode_t mode);创建命名管道 int main(int argc,char *argv[]) {mkfifo(p2,0644);return 0; } 匿名管道与命名管道的区别 匿名管道由pipe函数创建并打开命名管道由mkfifo函数创建打开用openFIFO命名管道与pipe匿名管道之间唯一的区别在于他们创建与打开的方式不同一旦这些工作完成之后他们具有相同的语义。 命名管道的打开规则 如果当前打开操作是为读而打开FIFO时 O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFOO_NONBLOCK enable:立刻返回成功 如果当前打开操作是为写而打开FIFO时O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFOO_NONBLOCK enable:立刻返回失败错误码为ENXIO system V共享内存 共享内存是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间这些进程间数据传递不在涉及到 内核换句话说是进程不在通过执行进入内核的系统调用来传递彼此的数据。 共享内存示意图 共享内存数据结构 共享内存函数 shmget函数 功能用来创建共享内存 原型int shmget(key_t key,size_t size,int shmflg); 参数 key共享内存段名字size共享内存大小shmflg由九个权限标志构成他们的用法和创建文件时使用的mode模式标志是一样的 返回值成功返回一个非负整数即该共享内存段的标识码失败返回-1 shmat函数 功能将共享内存段连接到地址空间 原型void *shmatint shmidconst void *shmaddrint 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表示连接操作用来只读共享内存 进程间通信的前提是让不同的进程看到同一份资源 ipcs函数 下面来看一段代码 comm.hpp #ifndef __COM_HPP__#define __COM_HPP__#includeiostream #includesys/ipc.h #includesys/shm.h #includesys/types.h #includecerrno #includecstring #includecstdio #includestringusing namespace std;//单独使用IPC_CREAT:创建一个共享内存如果共享内存不存在就创建如果已经存在获取已经存在的共享内存并返回 //IPC_EXCL不能单独使用一般都要配合IPC_CREAT //IPC_CREAT|IPC_EXCL创建一个共享内存如果共享内存不存在就创建如果已经存在就立马出错返回//只要没出错就是成功创建了新的共享内存#define PATHNAME . #define PROID 0x6666const int gsize4096;//字节为单位 key_t getkey() {key_t k ftok(PATHNAME,PROID);if(k-1){cerrerror:errno:strerror(errno)endl;exit(1);}return k; } string toHex(int x) {char buffer[64];snprintf(buffer,sizeof(buffer),0x%x,x);return buffer; } static int createShmHelper(key_t k,int size,int flag) {int shmid shmget(k,gsize,flag);if(shmid-1){cerrerror:errno:strerror(errno)endl;exit(2);}return shmid; } int createShm(key_t k,int size) {return createShmHelper(k,size,IPC_CREAT|IPC_EXCL); } int getShm(key_t k,int size) {dreturn createShmHelper(k,size,IPC_CREAT); }#endif server.cc #includecomm.hppint main() {//创建keykey_t k getkey();coutserver key:toHex(k)endl;//2、创建共享内存int shmid createShm(k,gsize);coutserver shmid:toHex(shmid)endl;return 0; }client.cc #includecomm.hppint main() {key_t k getkey();coutclient key:toHex(k)endl;int shmid getShm(k,gsize);coutclient shmid:toHex(shmid)endl;return 0; }Makefile .PHONY:all all:client serverclient:client.ccg -o $ $^ -stdc11 server:server.ccg -o $ $^ -stdc11.PHONY:clean clean:rm -f client server 编译运行 通过ipcs查看信息 当我们重新编译运行程序时我们看到打印了错误信息,并且返回值为2 也就是说共享内存创建失败 进一步分析我们不难得知是因为共享内存在进程关闭之后还存在所以无法创建新的。 即是共享内存生命周期不随进程、随OS 那么我们应该怎么删除共享内存呢 ipcrm 我们可以用shmid删除共享内存 我们也可以使用key来删除共享内存 key VS shmid keyshmid类比文件系统里的inode类比文件系统里的fd系统层面用户层面 shmctl函数 功能用于控制共享内存 原型int shmctl(int shm,int cmd,struct shmid_ds *buf); 参数 shmid由shmget返回的共享内存标识码cmd将要采取的动作有三个可取值buf指向一个保存着共享内存的模式状态和访问权限的数据结构 返回值成功返回0失败返回-1 命令说明IPC_STAT把shmid_ds结构中的数据设置为共享内存的当前关联值IPC_SET在进程有足够权限的前提下把共享内存的当前关联值设置为shmid_ds数据结构中给出的值IPC_RMID删除共享内存段 注意 由于共享内存大小是向上对齐PAGE4KB使用者申请多少就给多少。我们在通信的时候没有使用任何接口。一旦共享内存映射到进程的地址空间该共享内存就直接被所有的进程直接看到了由于这种特性可以让进程通信的时候减少拷贝次数所以共享内存是所有进程间通信最快的一种。共享进程没有任何的保护机制同步互斥虽然速度快但是准确性会受到影响。
http://www.w-s-a.com/news/383110/

相关文章:

  • 做网站前需要做什么准备wordpress图片云储存
  • 查楼盘剩余房源的网站地方网站推广
  • 农家乐网站建设方案创意平面设计公司简介
  • 信息化建设 网站作用网络营销的形式网站营销
  • 沈阳出名网站潍坊正规建设网站
  • 计算机软件开发需要学什么沈阳网站关键字优化
  • 关于军队建设网站国内最好的wordpress主题
  • 小视频网站如何建设陪诊app开发
  • 英文网站首页优化国外手机网站源码
  • 网站建设公司如何找客户网站建设应该考虑哪些问题
  • 创新的江苏网站建设wordpress用户绑定手机
  • 自己做网赌网站网站设计者
  • 教育培训网站设计辽宁招标工程信息网
  • 韶关网站推广做网站要哪些人员
  • 建设银行网站链接开发公司与物业公司交接清单
  • 网站定位广告企业建网站有这个必要吗
  • 网站模板 商标黄冈建设工程信息网
  • 做鞋子的招聘网站有哪些微网站
  • 项目网站开发建网站 多少钱
  • wordpress做门户seo培训价格
  • 百度关键词优化软件如何wordpress站点地图优化
  • 使用cnnic证书的网站营销公司有哪些
  • 做电子杂志用什么网站如何将网站生成二维码
  • 三点水网站建设洛阳市建设厅网站
  • 哪家做网站便宜网络推广培训吧
  • 网站怎么做支付非凡软件站
  • 北京谁会做网站开发熊岳网站怎么做
  • 南阳哪有做网站公司定制网站本地企业
  • 平板上做网站的软件邀约网站怎么做请柬
  • 企业网站成品源码邯郸做网站流程