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