zoukankan      html  css  js  c++  java
  • Linux IPC实践(10) --Posix共享内存

    1. 创建/获取一个共享内存

    #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);

    参数:

       name:  共享内存名字;

       oflag: 与open函数类型, 可以是O_RDONLY, O_WRONLY, O_RDWR, 还可以按位或上O_CREAT, O_EXCL, O_TRUNC.

       mode: 此参数总是需要设置, 如果oflag没有指定O_CREAT, 则mode可以设置为0;

    返回值:

       成功: 返回一个文件描述符;

       失败: 返回-1;

    注意-Posix IPC名字限制:

       1. 必须以”/”开头, 并且后面不能还有”/”, 形如:/file-name;

       2. 名字长度不能超过NAME_MAX

       3. 链接时:Link with -lrt.

    /** 示例: 共享内存的打开与关闭 **/
    int main(int argc,char *argv[])
    {
        int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);
        if (shmid == -1)
            err_exit("shmget error");
    
        cout << "share memory open success" << endl;
        close(shmid);
    }

    2. 修改共享内存大小

    int ftruncate(int fd, off_t length);

    该函数不仅可用于修改共享内存大小, 而且可以用于修改文件大小

    /** 示例: 修改共享内存大小
    将其修改为一个Student结构体的大小
    **/
    struct Student
    {
        char name[32];
        int age;
    };
    int main(int argc,char *argv[])
    {
        int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);
        if (shmid == -1)
            err_exit("shmget error");
        if (ftruncate(shmid, sizeof(Student)) == -1)
            err_exit("ftruncate error");
    
        cout << "share memory change size success" << endl;
        close(shmid);
    }

    3. 获取共享内存状态

    int fstat(int fd, struct stat *buf);

    该函数不仅可用于获取共享内存状态, 而且可以用于获取文件状态, 与前面曾经讲述过的stat, lstat类型;

    //stat结构体
    struct stat
    {
        dev_t     st_dev;     /* ID of device containing file */
        ino_t     st_ino;     /* inode number */
        mode_t    st_mode;    /* protection */
        nlink_t   st_nlink;   /* number of hard links */
        uid_t     st_uid;     /* user ID of owner */
        gid_t     st_gid;     /* group ID of owner */
        dev_t     st_rdev;    /* device ID (if special file) */
        off_t     st_size;    /* total size, in bytes */
        blksize_t st_blksize; /* blocksize for filesystem I/O */
        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
        time_t    st_atime;   /* time of last access */
        time_t    st_mtime;   /* time of last modification */
        time_t    st_ctime;   /* time of last status change */
    };
    /** 示例: 获取共享内存的mode和size **/
    int main(int argc,char *argv[])
    {
        int shmid = shm_open("/xyz", O_RDWR|O_CREAT, 0666);
        if (shmid == -1)
            err_exit("shmget error");
        if (ftruncate(shmid, sizeof(Student)) == -1)
            err_exit("ftruncate error");
    
        struct stat buf;
        if (fstat(shmid, &buf) == -1)
            err_exit("lstat error");
        // 注意: 获取权限时, 需要&上0777, 而且要以%o, 八进制方式打印
        printf("mode: %o
    ", buf.st_mode&0777);
        printf("size: %ld
    ", buf.st_size);
    
        close(shmid);
    }

    4. 删除一个共享内存对象

    int shm_unlink(const char *name);
    //示例: 
    int main(int argc,char *argv[])
    {
        shm_unlink("/xyz");
    }

    5. 共享内存的映射/卸载

    #include <sys/mman.h>
    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    int munmap(void *addr, size_t length);

    参数:

       addr:  要映射的起始地址, 通常指定为NULL, 让内核自动选择;

       length: 映射到进程地址空间的字节数, 通常是先前已经创建的共享内存的大小;

       prot: 映射区保护方式(见下);

       flags: 标志(通常指定为MAP_SHARED, 用于进程间通信);

       fd: 文件描述符(填为shm_open返回的共享内存ID);

       offset: 从文件头开始的偏移量(一般填为0);

     

    prot

    说明

    PROT_READ

    页面可读

    PROT_WRITE

    页面可写

    PROC_EXEC

    页面可执行

    PROC_NONE

    页面不可访问

     

    flags

    说明

    MAP_SHARED

    变动是共享的

    MAP_PRIVATE

    变动是私有的

    MAP_FIXED

    准确解释addr参数, 如果不指定该参数, 则会以4K大小的内存进行对齐

    MAP_ANONYMOUS

    建立匿名映射区, 不涉及文件

     

    mmap返回值:

       成功: 返回映射到的内存区的起始地址;

       失败: 返回MAP_FAILED;

    注意:mmap失败返回EACCES错误的原因:

       EACCES A file descriptor refers to a non-regular file.  

    Or MAP_PRIVATE was requested, but fd  is  not  open for reading.  

    Or MAP_SHARED was requested and PROT_WRITE is set, but fd is not open 

    in read/write (O_RDWR) mode.  Or PROT_WRITE  is  set,  but  the file is append-only.

    /** 示例: 向共享内存写入数据 **/
    int main(int argc,char *argv[])
    {
        int shmid = shm_open("/xyz", O_RDWR, 0);
        if (shmid == -1)
            err_exit("shm_open error");
    
        struct stat buf;
        if (fstat(shmid, &buf) == -1)
            err_exit("fstat error");
        Student *p = (Student *)mmap(NULL, buf.st_size,
                                     PROT_WRITE, MAP_SHARED, shmid, 0);
        if (p == MAP_FAILED)
            err_exit("mmap error");
        strcpy(p->name, "Hadoop");
        p->age = 5;
    
        munmap(p, buf.st_size);
        close(shmid);
    }
    /** 从共享内存读出数据 **/
    int main(int argc,char *argv[])
    {
        int shmid = shm_open("/xyz", O_RDONLY, 0);
        if (shmid == -1)
            err_exit("shm_open error");
    
        struct stat buf;
        if (fstat(shmid, &buf) == -1)
            err_exit("fstat error");
        Student *p = (Student *)mmap(NULL, buf.st_size,
                                     PROT_READ, MAP_SHARED, shmid, 0);
        if (p == MAP_FAILED)
            err_exit("mmap error");
    
        cout << "name: " << p->name << ", age: " << p->age << endl;
    
        munmap(p, buf.st_size);
        close(shmid);
    }

    [附]

       -Posix共享内存默认创建在/dev/shm目录下

       -可以使用od命令查看共享内存的内容

    od -c /dev/shm/xyz

  • 相关阅读:
    Windows 10 IoT Core 17101 for Insider 版本更新
    Windows 10 IoT Core 17093 for Insider 版本更新
    Windows 10 IoT Serials 10 – 如何使用OCR引擎进行文字识别
    2017年全国大学生物联网设计竞赛(TI杯)华东分赛区决赛总结
    Windows 10 IoT Core 17083 for Insider 版本更新
    My Feedback for Windows 10 IoT Core on Feedback Hub App (4/1/2017-1/23/2018)
    为 Azure IoT Edge 设备部署 Azure Stream Analytics 服务
    Azure IoT Edge on Raspberry Pi 3 with Raspbian
    Azure IoT Edge on Windows 10 IoT Core
    Mixed Reality-宁波市VR/AR技术应用高研班总结
  • 原文地址:https://www.cnblogs.com/itrena/p/5926957.html
Copyright © 2011-2022 走看看