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

广东快速做网站公司哪家好asp网站301

广东快速做网站公司哪家好,asp网站301,国外做问卷网站,商务网站开发与建设共享内存的概念 共享内存让不同进程看到同一份资源的方式就是#xff0c;在物理内存当中申请一块内存空间#xff0c;然后将这块内存空间分别与各个进程各自的页表之间建立映射#xff0c;再在虚拟地址空间当中开辟空间并将虚拟地址填充到各自页表的对应位置#xff0c;使得…共享内存的概念 共享内存让不同进程看到同一份资源的方式就是在物理内存当中申请一块内存空间然后将这块内存空间分别与各个进程各自的页表之间建立映射再在虚拟地址空间当中开辟空间并将虚拟地址填充到各自页表的对应位置使得虚拟地址和物理地址之间建立起对应关系至此这些进程便看到了同一份物理内存这块物理内存就叫做共享内存。 注意 这里所说的开辟物理空间、建立映射等操作都是调用系统接口完成的也就是说这些动作都由操作系统来完成。 共享内存的数据结构 在系统当中可能会有大量的进程在进行通信因此系统当中就可能存在大量的共享内存那么操作系统必然要对其进行管理所以共享内存除了在内存当中真正开辟空间之外系统一定还要为共享内存维护相关的内核数据结构。 共享内存的数据结构如下 struct shmid_ds {struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /* size of segment (bytes) */__kernel_time_t shm_atime; /* last attach time */__kernel_time_t shm_dtime; /* last detach time */__kernel_time_t shm_ctime; /* last change time */__kernel_ipc_pid_t shm_cpid; /* pid of creator */__kernel_ipc_pid_t shm_lpid; /* pid of last operator */unsigned short shm_nattch; /* no. of current attaches */unsigned short shm_unused; /* compatibility */void *shm_unused2; /* ditto - used by DIPC */void *shm_unused3; /* unused */ };当我们申请了一块共享内存后为了让要实现通信的进程能够看到同一个共享内存因此每一个共享内存被申请时都有一个key值这个key值用于标识系统中共享内存的唯一性。         可以看到上面共享内存数据结构的第一个成员是shm_permshm_perm是一个ipc_perm类型的结构体变量每个共享内存的key值存储在shm_perm这个结构体变量当中其中ipc_perm结构体的定义如下 struct ipc_perm{__kernel_key_t key;__kernel_uid_t uid;__kernel_gid_t gid;__kernel_uid_t cuid;__kernel_gid_t cgid;__kernel_mode_t mode;unsigned short seq; };记录一下 共享内存的数据结构shmid_ds和ipc_perm结构体分别在/usr/include/linux/shm.h和/usr/include/linux/ipc.h中定义。 共享内存的建立与释放 共享内存的建立大致包括以下两个过程 在物理内存当中申请共享内存空间。将申请到的共享内存挂接到地址空间即建立映射关系。 共享内存的释放大致包括以下两个过程 将共享内存与地址空间去关联即取消映射关系。释放共享内存空间即将物理内存归还给系统。 共享内存的创建 创建共享内存我们需要用shmget函数shmget函数的函数原型如下 int shmget(key_t key, size_t size, int shmflg);shmget函数的参数说明 第一个参数key表示待创建共享内存在系统当中的唯一标识。第二个参数size表示待创建共享内存的大小。第三个参数shmflg表示创建共享内存的方式。 shmget函数的返回值说明 shmget调用成功返回一个有效的共享内存标识符用户层标识符。shmget调用失败返回-1。 注意我们把具有标定某种资源能力的东西叫做句柄而这里shmget函数的返回值实际上就是共享内存的句柄这个句柄可以在用户层标识共享内存当共享内存被创建后我们在后续使用共享内存的相关接口时都是需要通过这个句柄对指定共享内存进行各种操作。 传入shmget函数的第一个参数key需要我们使用ftok函数进行获取 ftok函数的函数原型如下 key_t ftok(const char *pathname, int proj_id);ftok函数的作用就是将一个已存在的路径名pathname和一个整数标识符proj_id转换成一个key值称为IPC键值在使用shmget函数获取共享内存时这个key值会被填充进维护共享内存的数据结构当中。需要注意的是pathname所指定的文件必须存在且可存取。 注意 使用ftok函数生成key值可能会产生冲突此时可以对传入ftok函数的参数进行修改。需要进行通信的各个进程在使用ftok函数获取key值时都需要采用同样的路径名和和整数标识符进而生成同一种key值然后才能找到同一个共享资源。 传入shmget函数的第三个参数shmflg常用的组合方式有以下两种 组合方式作用IPC_CREAT如果内核中不存在键值与key相等的共享内存则新建一个共享内存并返回该共享内存的句柄如果存在这样的共享内存则直接返回该共享内存的句柄IPC_CREAT | IPC_EXCL如果内核中不存在键值与key相等的共享内存则新建一个共享内存并返回该共享内存的句柄如果存在这样的共享内存则直接返回该共享内存的句柄 换句话说 使用组合IPC_CREAT一定会获得一个共享内存的句柄但无法确认该共享内存是否是新建的共享内存。使用组合IPC_CREAT | IPC_EXCL只有shmget函数调用成功时才会获得共享内存的句柄并且该共享内存一定是新建的共享内存。 至此我们就可以使用ftok和shmget函数创建一块共享内存了创建后我们可以将共享内存的key值和句柄进行打印以便观察代码如下 #include stdio.h #include sys/types.h #include sys/ipc.h #include sys/shm.h #include unistd.h#define PATHNAME /home/cl/Linuxcode/IPC/shm/server.c //路径名#define PROJ_ID 0x6666 //整数标识符 #define SIZE 4096 //共享内存的大小int main() {key_t key ftok(PATHNAME, PROJ_ID); //获取key值if (key 0){perror(ftok);return 1;}int shm shmget(key, SIZE, IPC_CREAT | IPC_EXCL); //创建新的共享内存if (shm 0){perror(shmget);return 2;}printf(key: %x\n, key); //打印key值printf(shm: %d\n, shm); //打印句柄return 0; }该代码编写完毕运行后我们可以看到输出的key值和句柄值 在Linux当中我们可以使用ipcs命令查看有关进程间通信设施的信息。 单独使用ipcs命令时会默认列出消息队列、共享内存以及信号量相关的信息若只想查看它们之间某一个的相关信息可以选择携带以下选项 -q列出消息队列相关信息。-m列出共享内存相关信息。-s列出信号量相关信息。 例如携带-m选项查看共享内存相关信息 此时根据ipcs命令的查看结果和我们的输出结果可以确认共享内存已经创建成功了。 ipcs命令输出的每列信息的含义如下 标题含义key系统区别各个共享内存的唯一标识shmid共享内存的用户层id句柄owner共享内存的拥有者perms共享内存的权限bytes共享内存的大小nattch关联共享内存的进程数status共享内存的状态 注意 key是在内核层面上保证共享内存唯一性的方式而shmid是在用户层面上保证共享内存的唯一性key和shmid之间的关系类似于fd和FILE*之间的的关系。 共享内存的释放 通过上面创建共享内存的实验可以发现当我们的进程运行完毕后申请的共享内存依旧存在并没有被操作系统释放。实际上管道是生命周期是随进程的而共享内存的生命周期是随内核的也就是说进程虽然已经退出但是曾经创建的共享内存不会随着进程的退出而释放。 这说明如果进程不主动删除创建的共享内存那么共享内存就会一直存在直到关机重启system V IPC都是如此同时也说明了IPC资源是由内核提供并维护的。 此时我们若是要将创建的共享内存释放有两个方法一就是使用命令释放共享内存二就是在进程通信完毕后调用释放共享内存的函数进行释放。 使用命令释放共享内存资源 我们可以使用ipcrm -m shmid命令释放指定id的共享内存资源。 [clVM-0-15-centos shm]$ ipcrm -m 8注意 指定删除时使用的是共享内存的用户层id即列表当中的shmid权柄。 使用程序释放共享内存资源 int shmctl(int shmid, int cmd, struct shmid_ds *buf);shmctl函数的参数说明 第一个参数shmid表示所控制共享内存的用户级标识符。第二个参数cmd表示具体的控制动作。第三个参数buf用于获取或设置所控制共享内存的数据结构。 shmctl函数的返回值说明 shmctl调用成功返回0。shmctl调用失败返回-1。 其中作为shmctl函数的第二个参数传入的常用的选项有以下三个 选项作用IPC_STAT获取共享内存的当前关联值此时参数buf作为输出型参数IPC_SET在进程有足够权限的前提下将共享内存的当前关联值设置为buf所指的数据结构中的值IPC_RMID删除共享内存段 例如在以下代码当中共享内存被创建两秒后程序自动移除共享内存再过两秒程序就会自动退出。 [clVM-0-15-centos shm]$ while :; do ipcs -m;echo ###################################;sleep 1;done共享内存的关联 将共享内存连接到进程地址空间我们需要用shmat函数shmat函数的函数原型如下 void *shmat(int shmid, const void *shmaddr, int shmflg);shmat函数的参数说明 第一个参数shmid表示待关联共享内存的用户级标识符。第二个参数shmaddr指定共享内存映射到进程地址空间的某一地址通常设置为NULL表示让内核自己决定一个合适的地址位置。第三个参数shmflg表示关联共享内存时设置的某些属性。 shmat函数的返回值说明 shmat调用成功返回共享内存映射到进程地址空间中的起始地址。shmat调用失败返回(void*)-1。 其中作为shmat函数的第三个参数传入的常用的选项有以下三个 选项作用SHM_RDONLY关联共享内存后只进行读取操作SHM_RND若shmaddr不为NULL则关联地址自动向下调整为SHMLBA的整数倍。公式shmaddr-(shmaddr%SHMLBA)0默认为读写权限 #include stdio.h #include sys/types.h #include sys/ipc.h #include sys/shm.h #include unistd.h#define PATHNAME /home/cl/Linuxcode/IPC/shm/server.c //路径名#define PROJ_ID 0x6666 //整数标识符 #define SIZE 4096 //共享内存的大小int main() {key_t key ftok(PATHNAME, PROJ_ID); //获取key值if (key 0){perror(ftok);return 1;}int shm shmget(key, SIZE, IPC_CREAT | IPC_EXCL); //创建新的共享内存if (shm 0){perror(shmget);return 2;}printf(key: %x\n, key); //打印key值printf(shm: %d\n, shm); //打印句柄printf(attach begin!\n);sleep(2);char* mem shmat(shm, NULL, 0); //关联共享内存if (mem (void*)-1){perror(shmat);return 1;}printf(attach end!\n);sleep(2);shmctl(shm, IPC_RMID, NULL); //释放共享内存return 0; }代码运行后发现关联失败主要原因是我们使用shmget函数创建共享内存时并没有对创建的共享内存设置权限所以创建出来的共享内存的默认权限为0即什么权限都没有因此server进程没有权限关联该共享内存。 我们应该在使用shmget函数创建共享内存时在其第三个参数处设置共享内存创建后的权限权限的设置规则与设置文件权限的规则相同。 int shm shmget(key, SIZE, IPC_CREAT | IPC_EXCL | 0666); //创建权限为0666的共享内存此时再运行程序即可发现关联该共享内存的进程数由0变成了1而共享内存的权限显示也不再是0而是我们设置的666权限。 共享内存的去关联 取消共享内存与进程地址空间之间的关联我们需要用shmdt函数shmdt函数的函数原型如下 int shmdt(const void *shmaddr);shmdt函数的参数说明 待去关联共享内存的起始地址即调用shmat函数时得到的起始地址。 shmdt函数的返回值说明 shmdt调用成功返回0。shmdt调用失败返回-1。 现在我们就能够取消共享内存与进程之间的关联了。 #include stdio.h #include sys/types.h #include sys/ipc.h #include sys/shm.h #include unistd.h#define PATHNAME /home/cl/Linuxcode/IPC/shm/server.c //路径名#define PROJ_ID 0x6666 //整数标识符 #define SIZE 4096 //共享内存的大小int main() {key_t key ftok(PATHNAME, PROJ_ID); //获取key值if (key 0){perror(ftok);return 1;}int shm shmget(key, SIZE, IPC_CREAT | IPC_EXCL | 0666); //创建新的共享内存if (shm 0){perror(shmget);return 2;}printf(key: %x\n, key); //打印key值printf(shm: %d\n, shm); //打印句柄printf(attach begin!\n);sleep(2);char* mem shmat(shm, NULL, 0); //关联共享内存if (mem (void*)-1){perror(shmat);return 1;}printf(attach end!\n);sleep(2);printf(detach begin!\n);sleep(2);shmdt(mem); //共享内存去关联printf(detach end!\n);sleep(2);shmctl(shm, IPC_RMID, NULL); //释放共享内存return 0; }运行程序通过监控即可发现该共享内存的关联数由1变为0的过程即取消了共享内存与该进程之间的关联。 注意 将共享内存段与当前进程脱离不等于删除共享内存只是取消了当前进程与该共享内存之间的联系。 共享内存与管道进行对比 当共享内存创建好后就不再需要调用系统接口进行通信了而管道创建好后仍需要read、write等系统接口进行通信。实际上共享内存是所有进程间通信方式中最快的一种通信方式。 从这张图可以看出使用管道通信的方式将一个文件从一个进程传输到另一个进程需要进行四次拷贝操作 服务端将信息从输入文件复制到服务端的临时缓冲区中。将服务端临时缓冲区的信息复制到管道中。客户端将信息从管道复制到客户端的缓冲区中。将客户端临时缓冲区的信息复制到输出文件中。 我们再来看看共享内存通信 从这张图可以看出使用共享内存进行通信将一个文件从一个进程传输到另一个进程只需要进行两次拷贝操作 从输入文件到共享内存。从共享内存到输出文件。 所以共享内存是所有进程间通信方式中最快的一种通信方式因为该通信方式需要进行的拷贝次数最少。 但是共享内存也是有缺点的我们知道管道是自带同步与互斥机制的但是共享内存并没有提供任何的保护机制包括同步与互斥。
http://www.zqtcl.cn/news/682428/

相关文章:

  • 做火情监控网站需要用什么系统做一个网站多少费用
  • 成都建设网站首页贺州网站建设
  • 硚口区建设局网站海绵宝宝的网页设计html源代码
  • 旅游网站建设合同成年做羞羞的视频网站
  • 海门网站建设制作道德建设 网站
  • 苏州 规划建设局网站网页设计师培训费用图
  • 怎么做视频解析的网站QQ空间可以建设网站吗
  • 视频网站 php源码甘肃 网站建设
  • 响应式网站和自适应便宜做网站8818
  • 湖南网站建设mxtia网站建设的流程图
  • 西安网站开发公司电话装修设计网站有哪些
  • 多少钱网站建设个人主页网页设计教程
  • 嘉兴品牌网站建设网站开发项目拖延周期
  • 网站版面布局结构网站建设公司公司
  • 给新公司建网站中国互联网企业排名前十名
  • 中国建设银行网站会员用户名网站建设应列入啥费用
  • 网站上面的水印怎么做的广东网站建设公
  • 爱站网关键词长尾挖掘工具wordpress文章外链
  • 做视频剪辑接私活的网站网站商城系统设计
  • thinkphp5做网站做网站需要准备资料
  • 门户网站平台建设方案建e室内设计网cad
  • 西安网站建设收费标准第五次全国经济普查
  • 成品网站货源1688免费襄阳公司网站建设
  • 2020国内十大小说网站排名365网站
  • 潍坊做网站的网络公司网页设计入门教材pdf
  • 影视公司网站建设wordpress 500ms
  • 旅游网站建设公司crm客户管理系统模板
  • 哪个网站有免费的模板阿里云上如何用iis做网站
  • 中山优化网站门户网站建设jz190
  • 湖州服装网站建设网站备案和域名备案区别