linux IPC 通信 study 五:posix共享内存

来源:互联网 发布:卜柯文淘宝星店 编辑:程序博客网 时间:2024/05/17 16:03

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();}}


0 0
原创粉丝点击