【问题标题】:How do unix-like OS implement IPC shared memory?类unix操作系统如何实现IPC共享内存?
【发布时间】:2010-08-26 03:59:05
【问题描述】:

伙计们。我想知道类 unix 的操作系统如何实现共享内存?访问系统 IPC 共享内存中的内存 unix 和访问普通用户空间内存有什么区别?

【问题讨论】:

    标签: operating-system unix


    【解决方案1】:

    进程内存受到保护:在您的程序之外,通常没有人可以访问它。这涉及“重要”的噱头:您的程序必须相信它拥有可供自己使用的整个可寻址空间,但事实并非如此。据我了解,进程的地址空间被分成 pages(我认为是 4k 块),内核对这些页面有某种索引,将它们映射到物理内存或其他设备(就像您的硬盘一样,这就是您处理内存映射文件的方式)。每当您的进程尝试访问内存地址时,它首先会转到该映射以查看地址实际指向的位置,然后按照请求进行访问。每当进程试图访问内核没有映射到任何地方的页面时,就会出现分段错误。

    因此,由于内存在某种程度上被抽象掉了,内核可以用它做各种技巧。共享内存必须是一种特殊情况,要求内核将页面从不同进程的地址空间映射到相同的物理位置。

    【讨论】:

    • 一种方法是在页表/TLB 中有一个 GLOBAL 位,将这些页面标记为共享。当然,在谈到分页内存时有效。
    • en.... 从程序的角度来看,映射的共享内存段和进程私有内存段似乎几乎相同。这是否意味着访问共享内存单元并不比访问普通内存单元更耗时?
    • @ppan:不。这并不意味着访问私有内存页面和访问共享内存页面之间有任何区别。只是对于共享内存,内核知道在某些情况下,两个程序可以映射到相同的物理内存位置。
    【解决方案2】:

    实际上正在使用的内存是受保护的。当两个或多个进程具有相同的东西时,我们将其映射并将其分配给一个特殊的内存段。该内存段可以从两个进程中访问。这是使用共享内存进行进程间通信的主要概念。

    Inter process communication using shared memory下面显示了一个小型共享内存示例。 (代码来自 John Fusco 的著作《Linux 程序员工具箱》,ISBN 0132198576,由 Prentice Hall Professional 于 2007 年 3 月出版,并在获得出版商许可的情况下使用。)代码实现了通过共享的父子进程进行通信的父子进程内存段。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/file.h>
    #include <sys/mman.h>
    #include <sys/wait.h>
     
    void error_and_die(const char *msg) {
      perror(msg);
      exit(EXIT_FAILURE);
    }
     
    int main(int argc, char *argv[]) {
      int r;
     
      const char *memname = "sample";
      const size_t region_size = sysconf(_SC_PAGE_SIZE);
     
      int fd = shm_open(memname, O_CREAT | O_TRUNC | O_RDWR, 0666);
      if (fd == -1)
        error_and_die("shm_open");
     
      r = ftruncate(fd, region_size);
      if (r != 0)
        error_and_die("ftruncate");
     
      void *ptr = mmap(0, region_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
      if (ptr == MAP_FAILED)
        error_and_die("mmap");
      close(fd);
     
      pid_t pid = fork();
     
      if (pid == 0) {
        u_long *d = (u_long *) ptr;
        *d = 0xdbeebee;
        exit(0);
      }
      else {
        int status;
        waitpid(pid, &status, 0);
        printf("child wrote %#lx\n", *(u_long *) ptr);
      }
     
      r = munmap(ptr, region_size);
      if (r != 0)
        error_and_die("munmap");
     
      r = shm_unlink(memname);
      if (r != 0)
        error_and_die("shm_unlink");
     
      return 0;
    }
    



    普通用户空间和共享内存空间的区别在于,在IPC的情况下,共享内存受到保护,而在其他情况下则不受保护。

    【讨论】:

      猜你喜欢
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2011-07-23
      相关资源
      最近更新 更多