- 这里简介一下共享内存的编程的模型,其它细节以后有时间再补充
- 创建共享内存,得到一个ID(函数shmget)
- 把ID映射成虚拟地址/挂载 (函数shmat)
- 使用虚拟地址访问内核共享内存,可以使用任何内存函数函数与运算符号
- 卸载虚拟地址 (函数shmdt)
- 删除共享内存 ,函数shctl(修改,获取共享内存的属性)
- 这里看下几个函数
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
对于创建共享内存的进程来讲,这个函数返回共享内存的Id,而对于接收方进程来讲,它通过这个函数来获取共享内存的Id,而如何获取到相同的Id则是由第一个参数key来决定的,大概可以理解为,创建共享内存的时候,把传入的key和内存的Id关联起来,等到接收方传入相同的key的时候,便会返回相同的Id.而保证key相同的办法则可以通过ftok函数利用相同的目录来获取,这里不作详述。只需要知道,传入相同的key就可以获取共享内存的Id即可。
第二个参数size则是共享内存的大小
第三个参数需要注意一下,一般来讲,创建者进程,一般传入IPC_CREAT|IPC_EXCL|权限,而作为接收方,传入0即可,其他细节请查看手册。
调用成功则返回Id,否则返回-1
对接收方进程而言,最后一个参数传入0即可。
接着调用shmat来得到共享内存,进行读写。shmdt来进行卸载
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr)
最后是shmctl
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
第一个参数是由shmget返回的Id
第二个参数cmd 则是选择工作的方式
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
一般我们用来删除Id的话,传入IPC_RMID即可,接收方不需要删除共享内存
举个栗子
shmA.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <signal.h>
key_t key;
int shmId;
int* p;
int i=0;
void handle(int s){
if(s==SIGINT){
shmdt(p);
shmctl(shmId,IPC_RMID,0);
exit(0);
}
}
int main(){
signal(SIGINT,handle);
//1. create shared memory
//
key=ftok(".",255);
if(key==-1)printf("ftok error,%m\n"),exit(-1);
shmId=shmget(key,4,IPC_CREAT|IPC_EXCL|0666);
if(shmId==-1)printf("shmget error,%m\n"),exit(-1);
//2. attach shared memory
p=shmat(shmId,0,0);
if(p==(int*)-1)printf("shmat error,%m\n"),exit(-1);
//3. use virtual address operate data
while(1){
*p=i++;;
sleep(1);
}
//4. deattach shared memory
//5. control(delete shared memory)
return 0;
}
shmB.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <signal.h>
key_t key;
int shmId;
int *p;
void handle(int s){
if(s==SIGINT){
shmdt(p);
exit(0);
}
}
int main(){
signal(SIGINT,handle);
//1. create shared memory
key=ftok(".",255);
if(key==-1)printf("ftok error,%m\n"),exit(-1);
shmId=shmget(key,4,0);
if(shmId==-1)printf("shmget error,%m\n"),exit(-1);
//2. attach shared memory
p=shmat(shmId,0,0);
if(p==(int*)-1)printf("shmat error,%m\n"),exit(-1);
//3. use virtual address operate data
while(1){
sleep(1);
printf("num=%d\n",*p);
}
//4. deattach shared memory
shmdt(p);
//5. control(delete shared memory)
//
return 0;
}