草庐IT

c - mremap(2) 与 HugeTLB 改变虚拟地址?

coder 2023-06-22 原文

Linux mremap(2) 函数是否可以将从 mmap() 获得的 HugeTLB 的虚拟地址更改为新的固定虚拟地址?

(背景:我想根据我得到的内存的物理地址重新映射虚拟地址。这是通过直接检查指针地址来有效地执行虚拟地址到物理地址的转换。我将使用内存从 DMA 到硬件用户空间。)

这似乎不适用于我的简单测试程序:

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>

#define LARGE_PAGE_SIZE (1024*1024*1024)

int main() {
  void *p1;
  void *p2;
  p1 = mmap(NULL, LARGE_PAGE_SIZE, PROT_READ|PROT_WRITE,
    MAP_SHARED|MAP_ANONYMOUS|MAP_HUGETLB|MAP_LOCKED,
    0, 0);
  if (p1 == MAP_FAILED) {
perror("mmap");
return 1;
  }
  printf("p1 = %p\n", p1);
  p2 = mremap(p1, LARGE_PAGE_SIZE, LARGE_PAGE_SIZE,
      MREMAP_MAYMOVE|MREMAP_FIXED,
      (void*)(((uint64_t)p1) | 0x500000000000ULL));
  if (p2 == MAP_FAILED) {
perror("mremap");
return 1;
  }
  printf("p2 = %p\n", p2);
}

mmap() 成功,mremap() 失败:

$ gcc -o mremap_hugetlb mremap_hugetlb.c && sudo ./mremap_hugetlb
p1 = 0x2aaac0000000
mremap: Invalid argument

请注意,新地址是根据原始 mmap() 获得的地址计算得出的。这很重要。无法提前知道所需的地址,因此我不能简单地将 MAP_FIXED 传递给 mmap()。

我目前使用的解决方法是使 mmap() 文件支持,这样我就可以在固定地址再次对它进行 mmap(),并 munmap() 旧映射。这是次优的,因为它需要我找到一个挂载的 hugetlbfs 文件系统,我不喜欢这种依赖的复杂性。

基于解决方法的当前代码: https://github.com/lukego/snabbswitch/blob/straightline/src/core/memory.c#L56

最佳答案

现在看来您必须使用 hugetlbfs。

除非我弄错了,否则问题出现在 Linux 内核中,因为 mm/mremap.c:mremap_to()电话 mm/mremap.c:vma_to_resize() ,这fails with EINVAL for huge pages .

也许测试不正确,或者函数缺少正确处理大页面的代码。我想知道是否应该联系 linux-kernellinux-mm邮件列表,看看这是否是一个应该/可以轻松修复的错误。但是,这对依赖当前(和旧版)内核的用户没有帮助。

请记住,在文件描述符上使用 mmap() 时,您通常会使用不同的代码路径,因为每个文件系统都可以指定自己的 mmap 处理程序。对于 hugetlbfs,代码在 fs/hugetlbfs/inode.c:hugetlbfs_file_mmap() 中. 而且,正如您所说,该代码路径似乎适合您。

请注意,最好让用户配置 hugetlbfs 挂载点,而不是从 /proc/mounts 中扫描一个挂载点,因为这样系统管理员可以配置多个 hugetlbfs 挂载点,每个挂载点都有不同的配置,针对服务器上运行的每个服务。 (我希望您的服务不需要以 root 身份运行。)

关于c - mremap(2) 与 HugeTLB 改变虚拟地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27997934/

有关c - mremap(2) 与 HugeTLB 改变虚拟地址?的更多相关文章

  1. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  2. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  3. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  4. ruby - 改变替换的大小写 - 2

    我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}

  5. ruby-on-rails - 验证电子邮件地址是 Paypal 用户 - 2

    我想验证一个电子邮件地址是否是PayPal用户。是否有API调用来执行此操作?是否有执行此操作的ruby​​库?谢谢 最佳答案 GetVerifiedStatus来自PayPal'sAdaptiveAccounts平台会为您做这件事。PayPal没有任何codesamples或SDKs用于Ruby中的自适应帐户,但我确实找到了编写codeforGetVerifiedStatusinRuby的人.您需要更改该代码以检查他们拥有的帐户类型的唯一更改是更改if@xml['accountStatus']!=nilaccount_status

  6. ruby-on-rails - 从 Geocode 经纬度获取地址 - 2

    对于我的大部分应用程序,我从Geocoder获取城镇/城市的纬度、经度、邮政编码等。我只是投入城市和州,作为返回,我得到了我处于一个有field的场景中。该场所需要一个地址,我正在从另一个来源获取该场所的纬度和经度。使用Geocodergem,我可以通过给地址提供经纬度来获取地址吗? 最佳答案 在Rails控制台中运行。latitude=40.0397longitude=-76.30144geo_localization="#{latitude},#{longitude}"query=Geocoder.search(geo_loca

  7. ruby-on-rails - Rails 验证虚拟属性 - 2

    我这个模型:classBunny每当我提交一个表单来创建这个模型时,我都会收到以下错误:#的未定义方法“number_before_type_cast” 最佳答案 我通过将此方法添加到我的Bunny模型中解决了这个问题:defnumber_before_type_castnumberend我不喜欢它,但我想在有人发布更好的解决方案之前它会起作用。 关于ruby-on-rails-Rails验证虚拟属性,我们在StackOverflow上找到一个类似的问题: h

  8. ruby - 为什么我不能改变 self 的值(value)? - 2

    为什么我可以这样改变“self”:self.map!{|x|x*2}或者这样:self.replace(self.map{|x|x*2})但不是这样:self=self.map{|x|x*2}为什么Ruby不允许我更改“self”变量指向的对象,但允许我更改对象的属性? 最佳答案 不是答案,只是一个线索。a=[1,2]=>[1,2]a.object_id=>2938a.map!{|x|x*2}=>[2,4]a.object_id#differentdatabutstillthesameobject=>2938a.replace(a.

  9. ruby - 为什么括号内的换行符会改变算术结果? - 2

    为什么下面的表达式会这样解析?括号的优先级应该高于换行符,不是吗?3-(1+1)#=>13-(1+1)#=>2省略加号也会让表达式计算为2:3-(11)#=>2如果我声明为连续的换行符(转义)或将加号移动到第一行,则会实现所需的行为:3-(1\+1)#=>13-(1+1)#=>1 最佳答案 这是因为Ruby将新行识别为表达式的结尾,除非表达式不完整。例如,(1+1)与相同(1;+1)这与+1相同,因为返回了括号内的最后一个表达式。这进一步与1相同。如果行尾有+,则表达式不完整,因此会继续到下一行。这使得:3-(1+1)被解释为3-(

  10. 【云计算】私有云在VMware下虚拟机的创建与配置(图文教程) - 2

    【适用平台】私有云   说明:完成私有云部分是需要两台虚拟机的,分别为controller、compute两个节点,但我们只需配置一台,然后克隆就方便多啦!需要用到的映射文件:关于vm的安装我就不介绍的,毕竟挺简单的,下面让我们看看基于私有云模块中,虚拟机的搭建吧。1、创建新的虚拟机,这里一般我会选择自定义,毕竟后面的配置都要根据私有云相关来进行搭建,会比较复杂。(如果是基础的可以选择典型,典型的满足一般虚拟机的配置) 2、选择稍后安装操作系统会比较方便后续的选择,这里你也可以自己选择自己的映像文件(但不建议)  3、我们是基于Linux下操作的,所以选择Linux客户机操作系统,版本选择自己

随机推荐