您的位置:首页 > 其它

进程间通信——共享内存

2016-09-20 11:54 120 查看
1、IPC资源简介
除了管道、文件、以及信号以外,还有IPC这样一种进程间的通信手段。IPC的含义即就是进程间通信资源,它包含三种资源类型。
(1)、共享内存;
(2)、信号量;
(3)、消息队列;
使用ipcs可以查看当前系统中IPC资源的情况。




2、共享内存简介
共享内存简而言之就是一句话:各个进程都能够共同访问的共享的内存区域。
进程的特征:高度的独立性和封闭性,它能够直接访问的内存只能是自身所包含的。
共享内存为了达到多个进程访问的效果,必然是独立于所有进程之外的内存区域。共享内存最终是受到操作系统内核管理。
进程对于共享内存的操作与管理主要是:
(1)、申请创建一个共享内存区域(操作系统内核是不可能主动为进程创建共享内存的!),操作系统内核得到申请然后创建。
(2)、申请使用一个已存在的共享内存区域。
(3)、申请释放共享内存区域(操作系统内核也是不可能主动释放共享内存区域的!),操作系统内核得到申请然后释放。

3、对于共享内存的编程
(1)、需要使用API : shmget()方法。
int shmget(key_t key, size_t size, int shmflg);
key_t其实就是long,key就是关键字,size大小,shmflg表示这块内存区域的标志。
其返回值为共享内存ID(也就是一个编号)shmid,即就是某一个共享内存区域的唯一标识,该标识又是操作系统内核动态分配的。
代码实现创建一块共享内存
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>

int main(void){
key_t key;
key = 0xabc00000;
int ret = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0755);
if(ret == -1){
perror("");
return -1;
}
}
运行结果



ipcrm -m shmid:通过命令的方式删除共享内存。
(2)、说明key_t
i>、key_t是一个long类型,是IPC资源外部约定的key(关键)值,通过key值映射对应的唯一存在的某一个IPC资源。
ii>、通过key_t的值就能够判断某一个对应的共享内存区域在哪,是否已经创建等等。
iii>、一个key值只能映射一个共享内存区域,但同时还可以映射一个信号量,而且还能同时映射一个消息队列资源,于是就可以使用一个key值管理三种不同的资源。
(3)、shmget()函数第三个参数的使用细节:
取值
说明
IPC_CREAT
创建一个新的共享内存
IPC_EXCL
判断key对应的共享内存是否已经存在
(4)、key_t值的产生,有两种方式:
i>、把key值写死;
ii>、根据文件的inode编号生成。需要调用的API:ftok()方法,该方法是获取指定文件的inode编号在根据第二个参数计算得到最终的一个整型量。
共享内存的获取:使用shmget()方法即可。IPC_EXCL

4、共享内存的使用
共享内存的使用分为2个小的步骤:i>、建立进程与共享内存的映射关系;ii>、读/写(直接使用指针即可);iii>、如果对于共享内存的使用结束,此时就要断开与共享内存的映射。
对于第一步来说,需要使用的API:shmat()方法。
对于第三步来说,需要使用的API:shmdt()方法。
被映射正在使用共享内存是否此时可以执行删除操作呢?
:是,虽然可以执行删除操作,却不能将其直接删除掉。而是做了2个操作,i>、将其状态置为dest,ii>、将其key值置为0x00000000,IPC_PRIVATE值。
当共享内存处于dest(待回收状态),则将其资源设为"私有"(只能将该共享资源分享给其子进程,其它进程无法创建于该资源的使用)。

5、共享内存的控制
共享内存的控制信息可以通过shmctl()方法获取,会保存在struct_shmid_ds结构体中。

共享内存的控制主要是shmid_ds,即就是共享内存的控制信息。

API:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数:
shmid:就是要被控制的共享内存的编号。
cmd:看执行什么操作(1、获取共享内存信息;2、设置共享内存信息;3、删除共享内存)。
可用命令说明
IPC_STAT从内核中拷贝获取共享内存信息,将其保存到第三个参数指针所指向的空间
IPC_SET将第三个参数所指向的空间的值设置到内核的共享内存管理数据中
IPC_RMID删除共享内存
6、编程实现
写入共享内存的一方:
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>

int createShm(void){
key_t key = ftok("./tmp", 7);
int shmid = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0755);

return shmid;
}

int main(void){
int shmid = createShm();
if(shmid == -1){
perror("");
return -1;
}
char *shmptr = (char *)shmat(shmid, NULL, 0);
if(shmptr == NULL){
perror("");
return -1;
}

sprintf(shmptr, "Hello I am writer, write to shm");

return 0;
}
从共享内存读出的一方:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>

int getShm(void){
key_t key = ftok("./tmp", 7);
return shmget(key, 256, IPC_EXCL | 0755);
}

int main(void){
int shmid = getShm();
if(shmid == -1){
perror("");
return -1;
}
char *shmptr = (char *)shmat(shmid, NULL, 0);
if(shmptr == NULL){
perror("");
return -1;
}
char buf[80];
memset(buf, 0, sizeof(buf));
strncpy(buf, shmptr, 80);
printf("buf content : %s\n", buf);

return 0;
}
运行结果






共享内存的应用场景
a) 应用场景:将共享内存视作公告板;
b) 方式与规则:i>、通常只有少量的进程对其进行写操作,大部分的进程只能进行读操作;
ii>、独占的写方式,写的时候既不能其它进程写也不能其它进程读。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  共享内存 shmat shmget