【发布时间】:2010-08-26 03:59:05
【问题描述】:
伙计们。我想知道类 unix 的操作系统如何实现共享内存?访问系统 IPC 共享内存中的内存 unix 和访问普通用户空间内存有什么区别?
【问题讨论】:
标签: operating-system unix
伙计们。我想知道类 unix 的操作系统如何实现共享内存?访问系统 IPC 共享内存中的内存 unix 和访问普通用户空间内存有什么区别?
【问题讨论】:
标签: operating-system unix
进程内存受到保护:在您的程序之外,通常没有人可以访问它。这涉及“重要”的噱头:您的程序必须相信它拥有可供自己使用的整个可寻址空间,但事实并非如此。据我了解,进程的地址空间被分成 pages(我认为是 4k 块),内核对这些页面有某种索引,将它们映射到物理内存或其他设备(就像您的硬盘一样,这就是您处理内存映射文件的方式)。每当您的进程尝试访问内存地址时,它首先会转到该映射以查看地址实际指向的位置,然后按照请求进行访问。每当进程试图访问内核没有映射到任何地方的页面时,就会出现分段错误。
因此,由于内存在某种程度上被抽象掉了,内核可以用它做各种技巧。共享内存必须是一种特殊情况,要求内核将页面从不同进程的地址空间映射到相同的物理位置。
【讨论】:
实际上正在使用的内存是受保护的。当两个或多个进程具有相同的东西时,我们将其映射并将其分配给一个特殊的内存段。该内存段可以从两个进程中访问。这是使用共享内存进行进程间通信的主要概念。
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的情况下,共享内存受到保护,而在其他情况下则不受保护。
【讨论】: