进程间通信:共享内存
来源:互联网 发布:美国医学数据库 编辑:程序博客网 时间:2024/06/11 11:03
系统V的IPC通信机制包括了消息队列、共享内存和信号量。每一种IPC结构结构都有一个非负整数标志,当创建一个IPC结构时,调用进程都必须提供一个类型为key_t的键(key)。操作系统把这个键转换为一个IPC的唯一标识符。
可以使用以下方式来指定一个键,调用函数如下:
#include <sys/types.h>#include <sys/ipc.h>key_t ftok(const char* path, int projectid);
创建好以后就可以使用这个键去创建一个新的IPC结构了。服务器只需要调用合适的get函数去创建就好了。这里我们主要谈论共享内存。
一. 共享内存
顾名思义,通过共享一块内存空间,其他进程不需要进行读取操作就可以看到一份公共资源,从而进行相互交换信息,但是共享内存之中不提供同步与互斥机制,这就需要我们用户自己去设计,简单的就是执行PV操作了。
要使用一个共享内存段,进程就必须获得该共享内存段的标志符,这里可以使用shmget函数,源码如下:
#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, int size, int shmflg);
参数size指定了共享内存段的大小,建议制定为页的整数倍,参数key制定了该共享内存段使用的key,可以使用ftok得到,参数shmflg可以设置为IPC_CREAT和IPC_EXCL,两个同时设置代表
如果共享内存段不存在则创建,如果存在则返回一个标识符,只使用IPC_CREAT时代表共享内存段存在则打开,不存在则返回-1,同时将失败原因保存在errno中。
创建了一个共享内存段后就要对他进行一系列的操作,比如,删除。这里就要使用shmctl函数:
#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds* buf);
参数shmid包括了共享内存段的标识符,参数buf指向一个类型为struct_ds的结构体,定义了内存段的性质:
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 */};
参数cmd可以设置为IPC_RMID,表示从系统中删除shmid指定共享内存段的标识符,并删除相应的数据结构。
如果一个进程要使用一个共享内存段,他必须连接该内存段,也就是说必须将内存段映射到进程的地址空间。可以使用shmat函数:
#include <sys/types.h>#include <sys/ipc.h>#include <shm.h>void *shmat(int shmid, void* shmaddr, int shmflg);
参数shmid指定了要连接的共享内存段的标识符;
参数shmaddr指定了共享内存的地址,一般设置为0,表示由系统选择,因为系统是最了解地址的;
参数shmflg包括了常量SHM_RDONLY,那么内存段就是只读的,否则就是读写的,如果成功连接,返回开始地址,否则返回(void*)-1,同时将失败原因保存在errno中。
在使用完共享内存段以后,进程可以使用shmdt来断开连接;
#include <sys/types.h>#include <sys/ipc.h>#include <shm.h>void *shmdt(void* shmaddr);
参数是shmat的返回值。
二.共享内存代码
//头文件comm.h#ifndef _COMM_H_#define _COMM_H_#include <stdio.h>#include <sys/ipc.h>#include <sys/shm.h>#define PATHNAME "."#define PROJ_ID 0x6666int creatShm(int size); //共享内存的创建int destroyShm(int shmid);//共享内存的销毁int getShm(int size); //共享内存获取#endif //_COMM_H_H
//comm.c#include "comm.h"static int commShm(int size,int flags){ key_t key = ftok(PATHNAME, PROJ_ID); //key值获取 if(key<0){ perror("ftok"); return -1; } int shmid = shmget(key, size, flags); //创建共享内存 if(shmid<0){ perror("shmget"); return -2; } return shmid;}int creatShm(int size){ return commShm(size, IPC_CREAT|IPC_EXCL|0666);}int destroyShm(int shmid){ if(shmctl(shmid, IPC_RMID, 0)<0){ //共享内存销毁 perror("shmctl"); return -2; } return 0;}int getShm(int size){ return commShm(size,IPC_CREAT);}
///server.c#include "comm.h"int main(){ int shmid = creatShm(4096); //创建 sleep(4); char * addr = (char*)shmat(shmid, NULL, 0); //连接内存段 sleep(3); while(1){ printf("%s\n", addr); sleep(1); } shmdt(addr); //断开连接 destroyShm(shmid); //销毁共享内存 return 0;}
#include "comm.h"int main(){ int shmid = getShm(4096); //打开共享内存 sleep(4); char * addr = (char*)shmat(shmid, NULL, 0); //连接 sleep(3); int i = 0; while(1){ //在内存中写入数据 addr[i] = 'A' + i; i++; addr[i] = 0; sleep(1); } shmdt(addr); //断开连接 return 0;}
- 进程间通信-共享内存
- 进程间通信---共享内存
- 进程间通信--共享内存
- 进程间通信--共享内存
- 进程间通信-共享内存
- 进程间通信共享内存
- 进程间通信-共享内存
- 进程间通信---共享内存
- 进程间通信----共享内存
- 【进程间通信】共享内存
- 进程间通信共享内存
- 进程间通信----共享内存
- 进程间通信---共享内存
- 进程间通信--------共享内存
- 进程间通信---共享内存
- 进程间通信-共享内存
- 进程间通信----共享内存
- 进程间通信---共享内存
- Eclipse没有装,怎么修改数据库的链接,一招教会你
- 泛型编程
- 01 进程和线程之由来
- 刚接触docker的备忘记录
- Java实现DES加密解密算法
- 进程间通信:共享内存
- fock炸弹
- 解决Qt"Unable to set geometry"问题
- extjs点击属性名如何让store不加载
- ajax清除缓存
- mysql 将A表数据插入到B表
- getDimension,getDimensionPixelSize,getDimensionPixelOffset三者的区别
- Java基础第10讲-面向对象之方法的重写和重载
- Linux虚拟主机配置(基于域名)