Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.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
如何在Linux中为内存映射文件提供写时扩展功能?_Linux_Posix_Aix - Fatal编程技术网

如何在Linux中为内存映射文件提供写时扩展功能?

如何在Linux中为内存映射文件提供写时扩展功能?,linux,posix,aix,Linux,Posix,Aix,我正在将一些代码从AIX移植到Linux。部分代码使用创建新文件。在可写模式下与SHM_MAP一起使用时,可以将文件扩展到其原始长度之外(在我的情况下为零): 将文件映射到段时,通过访问该段来引用该文件。内存分页系统会自动处理物理I/O。文件末尾以外的引用会导致文件以页面大小增量扩展。文件不能扩展到下一段边界之外 (AIX中的“段”是256MB的地址空间块,“页”通常为4KB。) 我希望在Linux上执行以下操作: 保留一大块地址空间(不必大到256MB,这些文件不是那么大) 设置页面保护位,

我正在将一些代码从AIX移植到Linux。部分代码使用创建新文件。在可写模式下与
SHM_MAP
一起使用时,可以将文件扩展到其原始长度之外(在我的情况下为零):

将文件映射到段时,通过访问该段来引用该文件。内存分页系统会自动处理物理I/O。文件末尾以外的引用会导致文件以页面大小增量扩展。文件不能扩展到下一段边界之外

(AIX中的“段”是256MB的地址空间块,“页”通常为4KB。)

我希望在Linux上执行以下操作:

  • 保留一大块地址空间(不必大到256MB,这些文件不是那么大)
  • 设置页面保护位,以便在首次访问之前未接触过的页面时生成SEGFULT
  • 对于页面错误,清除“导致页面错误”位并为页面分配提交内存,允许导致页面错误的写入(或读取)继续
  • 关闭共享内存区域后,将修改的页面写入文件
我知道我可以在Windows上使用该功能、
PAGE\u-GUARD
内存保护位和一个。Linux上的相应方法是什么?是否有更好的方法在Linux上实现这种写上扩展功能

我已经考虑过:

  • 使用带有固定大小的
    mmap()
    ,但我无法确定应用程序代码写入了多少文件
  • 分配一个大容量的匿名共享内存区域,但我同样不能说出有多少区域被写入
  • mmap()
    本身似乎没有提供任何扩展备份文件长度的工具

当然,我希望只对应用程序代码进行最小的更改就可以做到这一点。

我自己也考虑过类似的事情,但也没有找到任何方法让
mmap()
扩展支持文件

目前,我计划尝试两种选择:

  • 手动管理文件大小,自己扩展它,然后
    mremap()
    '
  • 创建一个稀疏文件,并希望VM在刷新脏页时分配所需的扇区

老实说,我认为稀疏文件不起作用,但值得一试。

根据您的喜好分配一个大的缓冲区,然后使用mprotect()*系统调用使缓冲区的尾部成为只读,并为SIGSEGV注册一个信号处理程序,以记下之前写入的位置,并再次使用mprotect()启用写入

    • 这与我曾经做的作业非常相似。基本上,我有一个“页面”列表和一个“框架”列表,以及相关信息。使用
      SIGSEGV
      我将捕获故障并根据需要更改内存保护位。我将包括您可能会发现有用的部分

      创建映射。最初它没有权限。 安装信号处理器 加强保护
      int-w\u-protect\u映射(void*addr,size\u-num\u-pages,w\u-prot\t-protection)
      {
      int-prot;
      开关(保护){
      案例保护\u无:
      prot=prot_NONE;
      打破
      案例保护内容如下:
      prot=prot_READ;
      打破
      案例保护\u写入:
      prot=prot_读取| prot_写入;
      打破
      }
      if(保护(地址,页数*获取页数大小(),保护)<0)
      返回FALSE;
      返回TRUE;
      }
      

      由于团队可能会再次使用相同的作业,我无法公开所有作业。

      非常好,谢谢!这在结构上与我之前在Windows上所做的非常相似。
      int w_create_mapping(size_t size, void **addr)
      {
      
          *addr = mmap(NULL,
                  size * w_get_page_size(),
                  PROT_NONE,
                  MAP_ANONYMOUS | MAP_PRIVATE,
                  -1,
                  0
          );
      
          if (*addr == MAP_FAILED) {
              perror("mmap");
              return FALSE;
          }
      
          return TRUE;
      }
      
      int w_set_exception_handler(w_exception_handler_t handler)
      {
          static struct sigaction sa;
          sa.sa_sigaction = handler;
          sigemptyset(&sa.sa_mask);
          sigaddset(&sa.sa_mask, SIGSEGV);
          sa.sa_flags = SA_SIGINFO;
      
          if (sigaction(SIGSEGV, &sa, &previous_action) < 0)
              return FALSE;
      
          return TRUE;
      }
      
      static void fault_handler(int signum, siginfo_t *info, void *context)
      {
          void *address;      /* the address that faulted */
      
          /* Memory location which caused fault */
          address = info->si_addr;
      
          if (FALSE == page_fault(address)) {
              _exit(1);
          }
      }
      
      int w_protect_mapping(void *addr, size_t num_pages, w_prot_t protection)
      {
          int prot;
      
          switch (protection) {
          case PROTECTION_NONE:
              prot = PROT_NONE;
              break;
          case PROTECTION_READ:
              prot = PROT_READ;
              break;
          case PROTECTION_WRITE:
              prot = PROT_READ | PROT_WRITE;
              break;
          }
      
          if (mprotect(addr, num_pages * w_get_page_size(), prot) < 0)
              return FALSE;
      
          return TRUE;
      }