API介绍
- shm_open
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
int shm_open(const char *name, int oflag, mode_t mode);
函数执行成功返回shm描述符,失败返回-1,errno指示错误信息
功能:创建一个新的share memory或者打开一个已经存在的share memory
参数name,shm标识字符串,形如“/somename”
参数oflag:
O_RDONLY,只读方式,mmap时只能使用PROT_READ
O_RDWR,读写方式
O_CREAT,如果不存在就创建,存在就返回
O_EXCL,如果存在就报错
O_TRUNC,如果shm已经存在,将它的大小弄成0
参数mode: 表示访问权限,比如0644
- ftruncate
int ftruncate(int fd, off_t length);
函数执行成功返回0,失败返回-1,errno指示错误信息
功能:设置shm的大小
- mmap
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
函数执行成功返回进程内地址,失败返回-1,errno指示错误信息
是一个系统调用,将shm和进程内的地址关联起来
参数addr:映射区的起始地址,设置为NULL则由系统决定映射区的起始地址
参数length:映射区的长度,不足一个内存页按一页处理
参数prot:映射区的保护模式,不能和shm_open中的oflag冲突
PROT_EXEC,页内容可以执行
PROT_READ,页内容可以被读取
PROT_WRITE,页内容可以被写入
PROT_NONE, 页内容不可访问
参数flags:映射区是否可以共享,常设置为MAP_SHARED
参数fd:
通过shm_open获得
参数offset
被映射内容的起始点
- munmap
int munmap(void *addr, size_t length);
函数执行成功返回0,失败返回-1,errno指示错误信息
系统调用
- close
#include <unistd.h>
int close(int fd);
函数执行成功返回0,失败返回-1,errno指示错误信息
功能:关闭share memory
- shm_unlink
int shm_unlink(const char *name);
函数执行成功返回0,失败返回-1,errno指示错误信息
功能:将shm_name和shm描述符分离
sample code
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define SHM_PATH "/this_key"
typedef struct {
int a;
int b;
int c;
}INFO;
int server()
{
int shmfd = 0;
INFO *info;
mode_t old_mode;
old_mode = umask(0);
shmfd = shm_open(SHM_PATH,
O_CREAT | O_EXCL | O_RDWR,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (shmfd < 0) {
if (errno == EEXIST) {
printf("%s\n", strerror(errno));
shmfd = shm_open(SHM_PATH, O_RDWR,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
} else {
return -1;
}
}
umask(old_mode);
ftruncate(shmfd, sizeof(INFO));
info = (INFO *)mmap(NULL, sizeof(INFO),
PROT_READ | PROT_WRITE,
MAP_SHARED,
shmfd, 0);
if (info == NULL) {
printf("failed to mmap\n");
goto exit;
return -2;
}
memset(info, 0, sizeof(INFO));
info->a = 1;
info->b = 1;
info->c = 0;
printf("server set info to shm is %d %d %d\n", info->a, info->b, info->c);
sleep(10);
munmap((void *)info, sizeof(INFO));
exit:
close(shmfd);
shm_unlink(SHM_PATH);
return 0;
}
int client()
{
int shmfd = shm_open(SHM_PATH, O_RDWR, 0666);
INFO *info;
ftruncate(shmfd, sizeof(INFO));
info = (INFO *)mmap(NULL, sizeof(INFO),
PROT_READ | PROT_WRITE,
MAP_SHARED,
shmfd, 0);
if (info == NULL) {
printf("failed to mmap\n");
goto exit;
return -2;
}
printf("\tclient get info from shm is %d %d %d\n", info->a, info->b, info->c);
munmap((void *)info, sizeof(INFO));
exit:
close(shmfd);
return 0;
}
int main(int argc, char **argv)
{
pid_t pid = fork();
if (pid == 0) {
sleep(1);
client();
} else if (pid > 0) {
server();
}
}