• Linux IPC 共享内存


    共享内存

    共享内存(shared memory)是最简单的Linux进程间通信方式之一

    使用共享内存,不同进程可以对同一块内存进行读写

    由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不需要进行额外系统调用或内核操作,同时还避免了多余的内存拷贝,所以,这种方式是效率最高、速度最快的进程间通信方式

    这种最大限度的自由也给共享内存带来了缺点:内核并不提供任何对共享内存访问的同步机制,比如 同时对共享内存的相同地址进行写操作,则后写的数据会覆盖之前的数据。所以,使用共享内存一般还需要使用其他IPC机制(如信号量)进行读写同步与互斥
    ---------------------

    基本原理

    了解Linux内存管理机制,就很容易知道共享内存的原理了。

    大家知道,内核对内存的管理是以页(page)为单位的,Linux下一般一个page大小是4k

    而程序本身的虚拟地址空间是线性的,所以内核管理了进程从虚拟地址空间到起对应的页的映射

    创建共享内存空间后,内核将不同进程虚拟地址的映射到同一个页面:所以在不同进程中,对共享内存所在的内存地址的访问最终都被映射到同一页面。下图演示了共享内存的工作机制
    ---------------------

    相关接口
      1)创建共享内存(SHared Memory GET):

      int shmget(key_t key, int size, int flag);
      返回:成功时返回一个和key相关的共享内存标识符,失败范湖范围-1。

      key:为共享内存段命名,多个共享同一片内存的进程使用同一个key。

      size:共享内存容量。

      flag:权限标志位,和open的mode参数一样。

       2)连接到共享内存地址空间(SHared Memory ATtach):

        void *shmat(int shmid, void *addr, int flag);
        返回:返回值即共享内存实际地址。

        shmid:shmget()返回的标识。

        addr:决定以什么方式连接地址。

        flag:访问模式。

      3)从共享内存分离(SHared Memory DeTach):

       int shmdt(const void *shmaddr); 
       返回:调用成功返回0,失败返回-1。

       shmaddr:是shmat()返回的地址指针。

    /*
     * a.c
     * write a random number between 0 and 999 to the shm every 1 second
    */
    #include<stdio.h>
    #include<unistd.h>
    #include<sys/shm.h>
    #include<stdlib.h>
    #include<error.h>
    int main(){
        int shm_id;
        int *share;
        int num;
        srand(time(NULL));
        shm_id = shmget (1234, getpagesize(), IPC_CREAT);//shm_id 就是 # ipc  -m  命令查询到的 linux中共享内存的keyid吧  注意运行结束后清理掉  使用ipcrm  -m    shm_id   清理
        if(shm_id == -1){
            perror("shmget()");
        }
        share = (int *)shmat(shm_id, 0, 0);
        while(1){
            num = random() % 1000;
            *share = num;
            printf("write a random number %d
    ", num);
            sleep(1);
        }
        return 0;
    }
    /*
     * b.c
     * read from the shm every 1 second
    */
    #include<stdio.h>
    #include<unistd.h>
    #include<sys/shm.h>
    #include<stdlib.h>
    #include<error.h>
    int main(){
        int shm_id;
        int *share;
        shm_id = shmget (1234, getpagesize(), IPC_CREAT);
        if(shm_id == -1){
            perror("shmget()");
        }
        share = (int *)shmat(shm_id, 0, 0);
        while(1){
            sleep(1);
            printf("%d
    ", *share);
        }
        return 0;
    }

    运行观察结果:

    运行时候通过ipcs -m查看共享内存的id 的情况   记得要释放掉共享的内存  如果不释放  下次 还是会被占用!!!!!!

    取得ipc信息:
    ipcs [-m|-q|-s]
    -m       输出有关共享内存(shared memory)的信息
    -q       输出有关信息队列(message queue)的信息
    -s       输出有关“遮断器”(semaphore)的信息
    # ipcs -m 
    IPC status from  as of 2007年04月10日 星期二 18时32分18秒 CST
    T          ID       KEY         MODE         OWNER     GROUP
    Shared Memory:
    m           0    0x50000d43 --rw-r--r--      root      root
    m         501    0x1e90c97c --rw-r-----    Oracle       dba

    清理掉共享内存

    #   ipcrm 命令   
    移除一个消息对象。或者共享内存段,或者一个信号集,同时会将与ipc对象相关链的数据也一起移除。当然,只有超级管理员,或者ipc对象的创建者才有这项权利啦

    ipcrm用法 
    ipcrm -M shmkey  移除用shmkey创建的共享内存段
    ipcrm -m shmid    移除用shmid标识的共享内存段
    ipcrm -Q msgkey  移除用msqkey创建的消息队列
    ipcrm -q msqid  移除用msqid标识的消息队列
    ipcrm -S semkey  移除用semkey创建的信号
    ipcrm -s semid  移除用semid标识的信号

  • 相关阅读:
    Unreal Engine 4 Based Materials
    PhysX Clothing for UE4
    UE4中使用URL图片
    开始创作自己的VR作品——VR故事叙述终极指南
    UE4里的自定义深度功能
    Mybatis27题
    java 备用待迁移
    几个算法题目
    数据结构算法题目
    Mybatis 面试题
  • 原文地址:https://www.cnblogs.com/zhangkele/p/9809453.html
Copyright © 2020-2023  润新知