Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Operating system 类unix操作系统如何实现IPC共享内存?_Operating System_Unix - Fatal编程技术网

Operating system 类unix操作系统如何实现IPC共享内存?

Operating system 类unix操作系统如何实现IPC共享内存?,operating-system,unix,Operating System,Unix,伙计们。我想知道类unix操作系统如何实现共享内存?访问普通用户空间内存和访问unix系统IPC共享内存之间的区别是什么 进程内存受到保护:在程序之外,通常没有人可以访问它。这涉及到“重要”的噱头:你的程序必须相信它拥有可供自己使用的全部可寻址空间,但事实并非如此。据我所知,进程的地址空间被划分为页面(我认为是4k块),内核对这些页面有某种索引,将它们映射到物理内存或其他设备(比如硬盘驱动器,这就是内存映射文件的方式)。每当您的进程尝试访问内存地址时,它都会首先转到该映射以查看地址实际指向的位置

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

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


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

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


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

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

下面显示了一个小型共享内存示例。(该代码源于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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效错误和死亡(常量字符*消息){
佩罗尔(味精);
退出(退出失败);
}
int main(int argc,char*argv[]){
INTR;
const char*memname=“样本”;
const size\u t region\u size=sysconf(\u SC\u PAGE\u size);
int fd=shm_open(memname,O_CREAT | O_TRUNC | O_RDWR,0666);
如果(fd==-1)
错误和模具(“shm_打开”);
r=ftruncate(fd,区域大小);
如果(r!=0)
错误和死亡(“ftruncate”);
void*ptr=mmap(0,区域大小,保护读取,保护写入,映射共享,fd,0);
如果(ptr==MAP_失败)
错误和死亡(“mmap”);
关闭(fd);
pid_t pid=fork();
如果(pid==0){
u_long*d=(u_long*)ptr;
*d=0xdbeebee;
出口(0);
}
否则{
智力状态;
waitpid(pid和status,0);
printf(“child writed%#lx\n”,*(u#u long*)ptr);
}
r=munmap(ptr,区域大小);
如果(r!=0)
错误和死亡(“munmap”);
r=shm_取消链接(memname);
如果(r!=0)
错误和死(“shm_取消链接”);
返回0;
}



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

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

下面显示了一个小型共享内存示例。(该代码源于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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效错误和死亡(常量字符*消息){
佩罗尔(味精);
退出(退出失败);
}
int main(int argc,char*argv[]){
INTR;
const char*memname=“样本”;
const size\u t region\u size=sysconf(\u SC\u PAGE\u size);
int fd=shm_open(memname,O_CREAT | O_TRUNC | O_RDWR,0666);
如果(fd==-1)
错误和模具(“shm_打开”);
r=ftruncate(fd,区域大小);
如果(r!=0)
错误和死亡(“ftruncate”);
void*ptr=mmap(0,区域大小,保护读取,保护写入,映射共享,fd,0);
如果(ptr==MAP_失败)
错误和死亡(“mmap”);
关闭(fd);
pid_t pid=fork();
如果(pid==0){
u_long*d=(u_long*)ptr;
*d=0xdbeebee;
出口(0);
}
否则{
智力状态;
waitpid(pid和status,0);
printf(“child writed%#lx\n”,*(u#u long*)ptr);
}
r=munmap(ptr,区域大小);
如果(r!=0)
错误和死亡(“munmap”);
r=shm_取消链接(memname);
如果(r!=0)
错误和死(“shm_取消链接”);
返回0;
}



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

一种方法是在IPC中设置一个全局位