作用
高效率传输大量数据
共享内存用法
- 定义一个唯一key(ftok)
- 构造一个共享内存对象(shmget)
- 共享内存映射(shmat)
- 解除共享内存映射(shmdt)
- 删除共享内存(shmctl RMID)
shmget函数
功能:获取共享内存对象的ID
函数原型:
int shmget(key_t key,int size,int shmflg)
参数:
- key:共享对象键值
- nsems:共享内存大小
- shmflg:
- IPC_CREATE:共享内存不存在则创建
- mode:共享内存的权限
返回值:
成功:共享内存ID
失败:-1
shmat函数
功能:映射共享内存
函数原型:
int shmat(int shmid,const void *shmaddr,int shmflg)
参数:
- shmid:共享内存ID
- shmaddr:映射地址,NULL为自动分配
- shmflg:
- SHM_RDONLY:只读方式映射
- 0:可读可写
返回值:
成功:共享内存首地址
失败:-1
shmdt函数
功能:解除共享内存映射
函数原型:
int shmdt(const void *shmaddr)
参数:
shmaddr:映射地址
返回值:
成功:0
失败:-1
shmctl函数
功能:获取或设置共享内存的相关属性
函数原型:
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
参数:
-
shmid:共享内存ID
-
cmd:
- IPC_STAT:获取共享内存的属性信息
- IPC_SET:设置共享内存的属性
- IPC_RMID:删除共享内存
-
buf:属性缓冲区
返回值:
成功:由cmd类型决定
失败:-1
实现代码
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <wait.h>
#include "sem.h"
int main(void)
{
char *shm = NULL;//分配的共享内存的原始首地址
int shmid;//共享内存标识符
int semid;//信号量标识符
pid_t pid;
//创建共享内存
shmid = shmget((key_t)1234, 4096, 0666 | IPC_CREAT);
if(shmid == -1)
{
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}
/** 打开信号量,不存在则创建 */
semid = semget((key_t)6666, 1, 0666|IPC_CREAT); /* 创建一个信号量*/
if(semid == -1)
{
printf("sem open fail\n");
exit(EXIT_FAILURE);
}
init_sem(semid, 0);
/** 创建一个进程 */
pid=fork();
if(pid <0 )
{
printf("fork fail\n");
exit(EXIT_FAILURE);
}
if(pid==0)
{
//子进程
//将共享内存连接到当前进程的地址空间
printf("子进程地址开始映射\r\n");
shm =shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
}
//设置共享内存数据
memcpy(shm,"hello shm",9);
printf("正在拷贝\r\n");
sem_v(semid);
exit(0);
}
else
{
//父进程
//阻塞,让子进程先行
sem_p(semid);
//将共享内存连接到当前进程的地址空间
printf("父进程地址开始映射\r\n");
shm =(char*)shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
}
printf("拷贝数据='%s'\r\n",shm);
printf("解除共享内存\r\n");
if(shmdt(shm) == -1)
{
printf("shmdt fail\n");
exit(EXIT_FAILURE);
}
printf("删除共享内存\r\n");
if(shmctl(shmid,IPC_RMID,NULL) == -1)
{
printf("shmdt fail\n");
exit(EXIT_FAILURE);
}
printf("删除信号量\r\n");
del_sem(semid);
//等待子进程退出
wait(NULL);
exit(0);
}
}