第三十五章 POSIX共享内存

POSIX共享内存函数介绍

shm_open

功能:
    用来创建或打开一个共享内存对象
原型:
    int shm_open(const char *name, int oflag, mode_t mode);
参数:
    name : 共享内存对象的名字(命名规则和POSIX消息队列一样)
    oflag :与open函数类似,可以是O_RDONLY、O_WRONLY、O_RDWR,还可以按位或上O_CREAT、O_EXCL、O_TRUNC等
    mode : 此参数总是需要设置,如果oflag没有指定O_CREAT,可以指定为0
 
返回值:
    成功 : 成功返回非负整数文件描述符
    失败 : -1

ftruncate

功能:
    修改共享内存的大小(还可以用来修改文件的大小)
原型:
    int ftruncate(int fd, off_t length);
参数:
    fd : 文件描述符
    length :长度
 
返回值:
    成功 : 0
    失败 : -1

fstat

功能:
    获取共享内存对象信息(还可以用来获取文件的信息)
原型:
    int fstat(int fd, struct stat *buf);
参数:
    fd : 文件描述符
    buf :返回共享内存状态
 
返回值:
    成功 : 0
    失败 : -1
功能:
    删除共享内存对象
原型:
    int shm_unlink(const char *name);
参数:
    name : 共享内存对象的名字
 
返回值:
    成功 : 0
    失败 : -1

mmap

功能:
    将共享内存对象映射到进程地址空间
原型:
    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数:
    addr : 要映射的起始地址,通常指定为NULL,让内核自动选择
    length : 映射到进程地址空间的字节数
    prot : 映射区保护方式
    flags : 标志
    fd : 文件描述符
    offset : 从文件头开始的偏移量
 
返回值:
    成功 : 成功返回映射到的内存的起始地址
    失败 : -1

POSIX共享内存示例

  共享内存已经自动挂载到/dev/shm目录下

shm_open.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include <sys/types.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct stu{
    char name[32];
    int age;
}STU;


int main(int argc, char const *argv[])
{

    int shmid;
    //创建一个共享内存
    //创建的时候指定的权限是0666,创建后不一定是666,它还取决于umask,公式 mode & ~umask
    shmid = shm_open("/xyz", O_CREAT|O_RDWR, 0666);
    if(shmid == -1)
        ERR_EXIT("shm_open");

    printf("shm_open success\n");

    //改变共享内存的大小
    if(ftruncate(shmid,sizeof(STU)) == -1)
        ERR_EXIT("ftruncate");

    //获取共享内存的信息
    struct stat buf;
    if(fstat(shmid, &buf) == -1)
        ERR_EXIT("fstat");

    printf("size : %ld mode : %o\n",buf.st_size, buf.st_mode & 0777);

    close(shmid);
    return 0;
}

shm_write.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include <sys/types.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct stu{
    char name[32];
    int age;
}STU;


int main(int argc, char const *argv[])
{

    int shmid;
    //创建一个共享内存

    shmid = shm_open("/xyz", O_RDWR, 0);
    if(shmid == -1)
        ERR_EXIT("shm_open");

    printf("shm_open success\n");

    //获取共享内存的信息
    struct stat buf;
    if(fstat(shmid, &buf) == -1)
        ERR_EXIT("fstat");

    STU *p;
    //如果指定了PROT_WRITE和MAP_SHARED,shm_open的oflag应该指定为O_RDWR,否则会出现mmap: Permission denied
    p = mmap(NULL, buf.st_size, PROT_WRITE, MAP_SHARED, shmid, 0);
    if(p == MAP_FAILED)
        ERR_EXIT("mmap");
    
    strcpy(p->name, "test");
    p->age = 20;

    close(shmid);
    return 0;
}

shm_read.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
#include <sys/types.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct stu{
    char name[32];
    int age;
}STU;


int main(int argc, char const *argv[])
{

    int shmid;
    //创建一个共享内存

    shmid = shm_open("/xyz", O_RDONLY, 0);
    if(shmid == -1)
        ERR_EXIT("shm_open");

    printf("shm_open success\n");

    //获取共享内存的信息
    struct stat buf;
    if(fstat(shmid, &buf) == -1)
        ERR_EXIT("fstat");

    STU *p;
    //如果指定了PROT_WRITE和MAP_SHARED,shm_open的oflag应该指定为O_RDWR,否则会出现mmap: Permission denied
    p = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, shmid, 0);
    if(p == MAP_FAILED)
        ERR_EXIT("mmap");
    
    printf("name : %s\n", p->name);
    printf("age : %d\n", p->age);

    close(shmid);
    return 0;
}

shm_unlink.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

int main(int argc, char const *argv[])
{

    shm_unlink("/xyz");
    return 0;
}
posted @ 2019-10-08 15:49  sfdevs  阅读(337)  评论(0编辑  收藏  举报