新时代文明实践站网址平台运营推广方案

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

新时代文明实践站网址,平台运营推广方案,广州房地产网站建设方案,广告传媒有限公司简介#x1f44d;作者主页#xff1a;进击的1 #x1f929; 专栏链接#xff1a;【1的Linux】 我们在前面的文章中提到过#xff0c;进程间的通信本质都是先看到同一块资源#xff0c;然后通过这同一块资源进行通信#xff0c;并且是单向的通信#xff0c;只能一端发#… 作者主页进击的1 专栏链接【1的Linux】 我们在前面的文章中提到过进程间的通信本质都是先看到同一块资源然后通过这同一块资源进行通信并且是单向的通信只能一端发一端进行读共享内存也是基于这样的原理而进行的通信与管道有异曲同工之处管道是基于文件拿到同一个文件的文件描述符而进行的通信需要调用对文件的读写操作函数因此要经过内核。而共享内存是不会的其是内存级的通信因此它的效率非常高。 ps:共享内存因为数据不需要在客户机和服务器端之间复制数据直接写到内存不用若干次数据拷贝所以这是最快的一种IPC。 那么是什么是共享内存呢 我们其实早已经和它见过面了 我们的共享内存就在共享区中。
我们通过OS申请一块物理内存作为共享内存进程间是独立的有自己的页表进程地址空间。两进程通过页表将这块物理内存映射到各自的进程地址空间此时他们就能够看到同一块资源啦 共享内存的提供者是OS共享内存不止有一块此时就需要将他们进行管理怎么管理呢六字真言先描述后组织 那么共享内存实质是什么呢—-共享内存块对应的内核数据结构。 共享内存的建立 shmget()函数 int shmget(key_t key, size_t size, int shmflg); 它的参数都是指什么呢 key : 通信的双方要保证看到的是同一块共享内存它是几不重要只要它在系统里唯一就行。相同的key就可以看到同一块空间了。 size : 共享内存的大小 shmflg 标志位 IPC_CREAT 创建共享内存若存在则获取不存在则创建 IPC_CREAT | IPC_EXCL 创建共享内存若存在报错返回若不存在创建。 IPC_EXCL单独使用没有意义。 返回值是一个整数 其类似于文件描述符一样是共享内存用户层的标识符。 那么key 值怎么获取才能使系统中唯一的呢 key_t ftok(const char *pathname, int proj_id) 我们调用ftok函数去生成一个唯一的key。 pathname指定的文件此文件必须存在且可存取 proj_id计划代号project ID ftok的典型实现是调用stat函数然后组合以下三个值 ① pathname所在的文件系统的信息stat结构的st_dev成员。 ② 该文件在本文件系统内的索引节点号(stat结构的st_ino成员)。 ③ proj_id的低序8位不能为0。 上述三个值的组合产生一个32位键。 创建出共享内存后我们需要将其挂接到我们需要进行通信的地址空间上我们用shmat来实现。 void *shmat(int shm_id, const void *shm_addr, int shmflg); 第一个参数shm_id是由shmget()函数返回的共享内存标识。 第二个参数shm_addr指定共享内存连接到当前进程中的地址位置通常为空表示让系统来选择共享内存的地址。 第三个参数shm_flg是一组标志位通常为0。 调用成功时返回一个指向共享内存第一个字节的指针如果调用失败返回 挂接完成后我们就可以进行通信了。 若向结束通信我们可以选择让进程和共享内存分离 我们使用shmdt() 函数实现。 int shmdt(const void *shmaddr); 参数shmaddr是shmat()函数返回的地址指针调用成功时返回0失败时返回-1. 该函数只是让进程和其分离并不会删除共享内存。 删除共享内存我们用shmctl函数。 int shmctl(int shm_id, int command, struct shmid_ds buf); 第一个参数shm_id是shmget()函数返回的共享内存标识符。 第二个参数command是要采取的操作它可以取下面的三个值 IPC_STAT把shmid_ds结构中的数据设置为共享内存的当前关联值即用共享内存的当前关联值覆盖shmid_ds的值。 IPC_SET如果进程有足够的权限就把共享内存的当前关联值设置为shmid_ds结构中给出的值 IPC_RMID删除共享内存段 第三个参数buf是一个结构指针它指向共享内存模式和访问权限的结构。 出来使用函数删除共享内存我们还可以用命令手动去删除 ipcs -m 用来查询存在的共享内存 ipcrm -mshmid 可以删除对应的共享内存 共享内存并未提供同步机制也就是说在第一个进程结束对共享内存的写操作之前并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问 下面我们利用管道来实现一个同步的共享内存 #pragma once #includeiostream #includesys/types.h #includesys/ipc.h #includesys/shm.h #includecassert #includeunistd.h #includecstring #includesys/stat.h #includefcntl.h #includeLOG.hpp #define IPC_PATH /home/hyp #define PROJ_id 0x66 //8位 #define SHM_SIZE 4096 //最好是页的整数倍 #define Fifo_Name ./fifoclass Init {public:Init(){umask(0);int nmkfifo(Fifo_Name,0666);//创建管道if(n-1){perror(mkfifo);exit(1);}}~Init(){unlink(Fifo_Name);}};int OPen_fifo(std::string fifo_name,std::string flag) {int fd-1;if(flagREAD){fdopen(fifo_name.c_str(),O_RDONLY);}else if(flagWRITE){fdopen(fifo_name.c_str(),O_WRONLY);}else{exit(2);}assert(fd!-1);return fd; } void Sendmessage(int fd) {int commd0;int swrite(fd,commd,sizeof commd);log(发送中…..,DEBUG)std::endl;assert(s!-1);}void Wait(int fd) {log(等待中…..,DEBUG)std::endl;int commd1;int sread(fd,commd,sizeof(commd));assert(s!-1); }//日志打印 #pragma once #includeiostream #includestring #ifndef _LOGH #define _LOGH#define DEBUG 0 #define NOTICE 1 #define WARNING 2 #define ERROR 3std::string mes[4]{DEBUG,NOTICE,WARNING,ERROR };std::ostream log(const std::string message,int level) {std::cout|mes[level]|message|;return std::cout; }#endif//发送端 #includecomm.hpp #includeLOG.hppint main() {key_t kftok(IPC_PATH,PROJ_id);if(k-1){perror(ftok);exit(1);}log(creat key done,DEBUG) client# k:kstd::endl;int shmidshmget(k,SHM_SIZE,0);assert(shmid0);log(creat shm done,DEBUG)std::endl;//将创建出的共享内存挂接到自己的地址空间中char shmaddr(char)shmat(shmid,nullptr,0);if(shmaddrnullptr){perror(shmat);exit(1);}log(attach shm success,DEBUG)std::endl;//使用int fd OPen_fifo(Fifo_Name,WRITE);while(true){//sleep(1);//char puts[1024];//fgets(shmaddr,10,stdin);//Sendmessage(shmaddr);Sendmessage(fd);int sread(0,shmaddr,SHM_SIZE-1);if(s0){shmaddr[s-1]\0;if(strcmp(shmaddr,quit)0){break;}}}close(fd);int nshmdt(shmaddr);if(n-1){perror(shmdt);exit(1);}log(detach shm success,DEBUG)std::endl;return 0; }//收端 #includecomm.hpp #includeLOG.hppInit init; int main() {key_t kftok(IPC_PATH,PROJ_id);if(k-1){perror(ftok);exit(1);}log(creat key done,DEBUG) server# k:kstd::endl;int shmidshmget(k,SHM_SIZE,IPC_CREAT|IPC_EXCL|0666);//通信的发起者assert(shmid0);log(creat shm done,DEBUG)std::endl;//将创建出的共享内存挂接到自己的地址空间中char shmaddr(char*)shmat(shmid,nullptr,0);if(shmaddrnullptr){perror(shmat);exit(1);}log(attach shm success,DEBUG)std::endl;//使用int fdOPen_fifo(Fifo_Name,READ);while(true){Wait(fd);printf(%s\n,shmaddr);if(strcmp(shmaddr,quit)0) break;}int xshmctl(shmid,IPC_RMID,0);assert(x!-1);log(delete shm success,DEBUG)std::endl;return 0; }为了让进程之间能够通信我们让其能够看到同一份资源但看到同一份资源也会带来一些时序问题从而造成数据不一致的问题。 我们上述的代码中是用加入管道的方式从而保证其同步性使得只有一个进程写完后另一个进程才能够去读。信号量也是解决同步机制的一种方法。 我们将多个进程看到的公共的一份资源称为临界资源。 把进程访问临界资源的代码称为临界区 多个执行流运行时互相干扰主要是我们不加保护的访问了临界资源在非临界区是没有影响的为了更好的进行临界区的保护我们让多执行流在任何时刻都只有一个进程能够进入临界区—-我们将其称为互斥。 原子性要么不做要么做完没有中间状态。 关于信号量我们在后面会有更加详细的解读。