美文网首页
初窥linux共享内存

初窥linux共享内存

作者: bailongxian | 来源:发表于2016-10-12 21:18 被阅读112次

    共享内存的linux IPC的一个方式。最简单的解释就是同一段物理内存被映射到不同进程的地址空间。任和一个被映射的进程对该内存的写操作对其他被映射是可见的。
    可以在命令查看当前系统共享内存的信息。


    下面我们有4个文件,分别是公共文件,shm_write(创建共享内存) shm_read(读取共享内存内容) shm_clean(清除共享内存内容) common.h一个公共文件

    common.h

      1 #ifndef _COMMON_H
      2 #define _COMMON_H
      3 
      4 #include <sys/types.h>
      5 #include <sys/stat.h>
      6 #include <sys/shm.h>
      7 #include <stdlib.h>
      8 
      9 #define SHM_KEY         0x00000010
     10 #define BUFFSIZE        0x00001000
     11 
     12 #define SHM_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
     13 
     14 struct shm_mm
     15 {
     16         int num;
     17         char buff[BUFFSIZE];
     18 };
     19 
     20 #endif
    
    

    shm_write.c

      1 #include "common.h"
      2 #include <stdio.h>
      3 
      4 int main()
      5 {
      6         int shmid;
      7         shmid = shmget(SHM_KEY, sizeof(struct shm_mm), IPC_EXCL|IPC_CREAT|SHM_PERMS);
      8         if(shmid == -1)
      9         {
     10                 printf("shmget failed\n");
     11                 exit(1);
     12         }
     13 
     14         struct shm_mm *pshm = shmat(shmid, NULL, 0);
     15         if(pshm == (void*)-1)
     16         {
     17                 printf("shmat failed\n");
     18                 exit(2);
     19         }
     20 
     21         pshm->num = 100;
     22         for(int i = 0; i < 10 && i < BUFFSIZE; i++)
     23         {
     24                 pshm->buff[i] = 'a';
     25         }
     26 
     27 }
    

    shm_read.c

      1 #include "common.h"
      2 #include <stdio.h>
      3 
      4 int main()
      5 {
      6         int shmid;
      7         shmid = shmget(SHM_KEY,0, 0);
      8         if(shmid == -1)
      9         {
     10                 printf("shmget failed\n");
     11                 exit(1);
     12         }
     13 
     14         struct shm_mm *pshm = shmat(shmid, NULL, 0);
     15         if(pshm == (void*)-1)
     16         {
     17                 printf("shmat failed\n");
     18                 exit(2);
     19         }
     20 
     21         printf("num=%d\n", pshm->num);
     22         for(int i = 0; i < 10 && i < BUFFSIZE; i++)
     23         {
     24                 printf("%c\t", pshm->buff[i]);
     25         }
     26          printf("\n");
     27 
     28         getchar();
     29         return 0;
     30 }
    
    

    shm_clean.c

      1 #include "common.h"
      2 #include <stdio.h>
      3 
      4 int main()
      5 {
      6         int shmid = shmget(SHM_KEY, 0, 0);
      7         if(-1 == shmid)
      8         {
      9                 printf("shmget failed\n");
     10                 exit(0);
     11         }
     12         int ret = shmctl(shmid, IPC_RMID, 0);
     13         if(-1 == ret)
     14         {
     15                 printf("shmctl failed\n");
     16                 exit(1);
     17         }
     18         return 0;
     19 }
    
    ![read_out.png](https://img.haomeiwen.com/i541012/8ff9b7b6ec4b5676.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    

    我们运行shm_write进程
    查看当前系统的共享内存

    2016-10-10 23-52-41屏幕截图.png

    我们可以看到最后一行, 第一列的就是我们代码里面的SHM_KEY 权限也是我们自己设定的 SHM_PERMS, 大小是sizeof(shm_mm)。 因为shm_write进程以退出,所以现在attach在该内存的进程数量为0。
    我们启动shm_read

    read_out.png

    read进程读到了write写进去的数据.
    现在我们可以启动clean进程清除刚才创建的贡献内存。也可以用命令 ipcrm -m shmid 清除掉对于的共享内存。

    通过上述实现,我们看到,当进程退出后,内核自动会把该进程和共享内存的映射给清掉,就是我们通过ipcs -m 看到的attach的子段。如果我们想在进程不退出就把这个映射这清掉。通过调用shmdt即可。

    和其他共享数据一下,当多个进程对同一个共享内存进行读写的时候,仍然会有竞争。所以我们需要一些如信号量,进程锁等高级的进程同步控制原语来进行同步操作。
    当然,共享内存还受到一些参数的影响.
    /proc/sys/kernel/shmall:限制系统用在共享内存上的内存总页数。注意是页数,单位为4k。
    /proc/sys/kernel/shmmax:限制一个共享内存段的最大长度,字节为单位。
    /proc/sys/kernel/shmmni:限制整个系统可创建的最大的共享内存段个数。

    相关文章

      网友评论

          本文标题:初窥linux共享内存

          本文链接:https://www.haomeiwen.com/subject/glivyttx.html