进程间通信-共享内存
共享内存介绍
- 共享内存是将分配的物理空间直接映射到进程的用户虚拟地址空间中,减少数据在内核空间缓存
- 共享内存是一种效率较高的进程间通讯的方式
- 在 Linux 系统中通过 ipcs -m 查看所有的共享内存
- 共享内存模型
共享内存创建
- 创建共享内存调用 shmget() 函数
函数头文件
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型
int shmget(key t key, size t size, int shmflg);
函数功能
创建一个共享内存,并返回 ID
函数参数
- key :由 ftok()函数返口
- size: 共享内存的大小
- shmflg: 共享内存标志
函数返回值
- 成功 : 返回 共享内存id
- 失败:返回 -1,并设置 errno
创建一个共享内存,并打印出共享内存ID
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define PATHNAME "."
#define PRO_ID 100
#define SZ 256
int main(void){
key_t key;
int shmid,ret;
key = ftok(PATHNAME,PRO_ID);
if(key == -1){
perror("[ERROR] ftok()");
exit(EXIT_FAILURE);
}
shmid = shmget(key,SZ,IPC_CREAT|0666);
if(shmid == -1){
perror("shmid():");
exit(EXIT_FAILURE);
}
printf("shmid=%d\n",shmid);
sleep(10);
ret = shmctl(shmid,IPC_RMID,NULL);
if(ret == -1){
perror("shmctl():");
exit(EXIT_FAILURE);
}
return 0;
}
共享内存映射
共享内存映射调用 shmat 函数
函数头文件
#include <sys/types.h>
#include <sys/shm.h>
函数原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
函数功能
将进程地址空间映射到共享内存上
函数参数
- shmid:共享内存id
- shmaddr: 指定映射的到进程地址空间的起始地址
- 指定为 NULL 时,由系统选择映射的地址
- shmflg: 共享内存标志,一般设置为 0
函数返回值 - 成功 : 返回映射到进程地址空间的起始地址
- 失败 :(void * )-1,并设置 errno
共享内存解除映射
解除共享映射调用 shmdt 函数
函数头文件
#include <sys/types.h>
#include <sys/shm.h>
函数原型
int shmdt(const void *shmaddr);
函数功能
解除进程地址空间与共享内存的映射
函数参数
shmaddr: 映射地址空间的起始地址
函数返回值
- 成功 : 返回 0
- 失败 : 返回 -1,并设置 errno
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>
#define PATHNAME "."
#define PRO_ID 100
#define SZ 256
int main(void){
key_t key;
int shmid,ret;
key = ftok(PATHNAME,PRO_ID);
if(key == -1){
perror("[ERROR] ftok()");
exit(EXIT_FAILURE);
}
shmid = shmget(key,SZ,IPC_CREAT|0666);
if(shmid == -1){
perror("shmid():");
exit(EXIT_FAILURE);
}
printf("shmid=%d\n",shmid);
void *addr = NULL;
addr = shmat(shmid,NULL,0);
if(addr == (void*)-1){
perror("[ERROR] shmat():");
exit(EXIT_FAILURE);
}
memset(addr,'A',10);
shmdt(addr);
return 0;
#if 0
sleep(10);
ret = shmctl(shmid,IPC_RMID,NULL);
if(ret == -1){
perror("shmctl():");
exit(EXIT_FAILURE);
}
return 0;
#endif
}
- shmread.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PATHNAME "."
#define PRO_ID 100
#define SZ 256
int main(){
key_t key;
int shmid,ret,i;
char buffer[10] = {0};
void *addr = NULL;
key = ftok(PATHNAME,PRO_ID);
if(key == -1){
perror("[ERROR] key()");
exit(EXIT_FAILURE);
}
shmid = shmget(key,SZ,IPC_CREAT|0666);
if(shmid == -1){
perror("shmget():");
exit(EXIT_FAILURE);
}
printf("shmid = %d\n",shmid);
addr = shmat(shmid,NULL,0);
if(addr == (void*)-1){
perror("shmat");
exit(EXIT_FAILURE);
}
memcpy(buffer,addr,10);
for(int i = 0;i < 10; i++){
printf("%c",buffer[i]);
}
putchar('\n');
shmdt(addr);
return 0;
}
- 在两个进程使用共享内存之间传输文件