在使用DPDK或者SPDK的时候,需要在进程刚启动的时候使用rte_eal_init初始化Environment Abstract Layer,应用进程会通过这个函数告诉EAL为它映射多大的hugepages,这通常通过ealargs的-m参数来指定,就像下面这样:

    char *ealargs[] = {
argv[0], // name
NULL, // core_mask(to be decided)
"-n 4", // number of memory channels per processor socket
"--proc-type=auto", // The type of process instance.
"-m 512",
};
// ....
int rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs);
if (rc < 0)
{
// error handles
}

  需要注意的是,此处-m指定的hugepages的大小需要小于系统可用的hugepages大小(系统可用的Hugepages大小可以通过 `cat /proc/meminfo  | grep Hugepage`查看。

但是!在系统运行一段时间后,就算是-m指定的hugepages的大小小于系统可用的Hugepages大小,EAL初始化的时候依然会panic掉,输出类似于下面的日志:

EAL: Detected 64 lcore(s)
EAL: Auto-detected process type: PRIMARY
EAL: No free hugepages reported in hugepages-1048576kB
EAL: Can only reserve 927 pages from 4096 requested
Current CONFIG_RTE_MAX_MEMSEG=256 is not enough
Please either increase it or request less amount of memory.
PANIC in rte_eal_init():
Cannot init memory

  本文简要介绍导致该问题的原因以及一些我尝试过的解法。

原因:通过阅读dpdk的代码可以发现,导致这个问题的原因,是EAL在初始化的时候,无法从操作系统的Hugepages中找到连续个数的大页面,这个连续个数,由宏RTE_MAX_MEMSEG,这个宏可以在编译dpdk的时候修改(修改config/common_base中的CONFIG_RTE_MAX_MEMSEG的值)。官方解释:These pages can be located anywhere in physical memory, and, although the DPDK EAL will attempt to allocate memory in contiguous blocks, it is possible that the pages will not be contiguous. In this case, the application is not able to allocate big memory pools. (自http://dpdk.readthedocs.io/en/v16.04/linux_gsg/build_sample_apps.html#running-a-sample-application)

解法一:

清空系统的hugepages,然后在重启应用进程:

rm -rf /dev/huagepages/*;
sh ./start_my_process.sh

  一般情况下,这个解法就能解决。但是在有些场景下,这个方法无法解决。

解法二:

      重新mount hagepage,然后再重启server:

umount /dev/hugepages
rm -rf /dev/hugepages
mkdir -p /dev/hugepages
mount -t hugetlbfs nodev /dev/hugepages

  still not work

解法三:

源代码中看到EAL在初始化的时候,会使用/var/run/.rte_config和/var/run/.rte_hugepage_info来读取hugepage的信息,怀疑是EAL重启时如果这两个文件存在的话,直接从它们里面读取旧的hugepage信息,于是尝试umount hugepage的同时删除这个文件:

清理hugepages环境:

HUGE_MOUNT_POINT=`cat /proc/mounts  | grep hugetlbfs | cut -d ' ' -f 2`

# Removes hugepage filesystem.
remove_mnt_huge()
{
echo "Unmounting ${HUGE_MOUNT_POINT} and removing directory"
grep -s '${HUGE_MOUNT_POINT}' /proc/mounts > /dev/null
if [ $? -eq 0 ] ; then
sudo umount ${HUGE_MOUNT_POINT}
fi
sleep 2
if [ -d ${HUGE_MOUNT_POINT} ] ; then
sudo rm -rf ${HUGE_MOUNT_POINT}
fi
} # Removes all reserved hugepages.
clear_huge_pages()
{
echo > .echo_tmp
for d in /sys/devices/system/node/node? ; do
echo "echo 0 > $d/hugepages/hugepages-${HUGE_PAGE_SIZE}/nr_hugepages" >> .echo_tmp
done
echo "Removing currently reserved hugepages"
sudo sh .echo_tmp
rm -f .echo_tmp rm -rf /var/run/.rte_config
rm -rf /var/run/.rte_hugepage_info remove_mnt_huge
}

重建hugepage:

create_hugepages()
{
echo 8192 > /proc/sys/vm/nr_hugepages echo "Creating /mnt/huge and mounting as hugetlbfs"
sudo mkdir -p /dev/hugepages grep -s '/dev/hugepages' /proc/mounts > /dev/null
if [ $? -ne 0 ] ; then
sudo mount -t hugetlbfs nodev /dev/hugepages
fi
}

解法四:

看到EAL在初始化的时候,使用RTE_MAX_MEMSEG来判断连续大页面个数,可以将RTE_MAX_MEMSEG更改成一个更宽松的值(大于默认值256)重新编译DPDK。

实际上,这不是一个好的解法,因为你无法知道RTE_MAX_MEMSEG调整成多少合适,而且,每次调整宏,都需要重新编译DPDK,这会给调试工作带来不必要的时间负担。

解法五:

上面的解法一、二、三其实都基于一个假设,那就是你使用dpdk的进程独占了操作系统的Hugepages,一旦这个假设不成立,那么解法一、二、三就都不一定能成功解掉这个问题。解法五脱离这个假设,从整个系统的角度去考虑Hugepages的问题。

我使用的基于3.10内核的操作系统,默认打开了透明大页面功能(Transparent Hugepages),这个功能会使操作系统看到有大页面存在的时候,会在应用进程或者内核进程申请大块内存的时候,优先为它们分配大页面,大页面无法分配时,才会分配传统的4KB页面,对透明大页面感兴趣的同学请移步上两篇博文。

使用下面的命令查看哪些进程占用了系统的大页面:

# grep -e AnonHugePages  /proc/*/smaps | awk  '{ if($2>4) print $0} ' |  awk -F "/"  '{print $0; system("ps -fp " $3)} '

  如果操作系统打开了透明大页面功能,同时应用进程机器上有其他耗内存的应用,上面的命令会看到很多大页面都被耗内存应用占用了。这也就是为什么使用dpdk的进程在启动的时候无法分配出连续的大页面的原因,大页面不是某个进程独占的,它是一个系统资源,如果透明大页面功能被打开,那么大页面会为所有进程服务。

到这里,问题就迎刃而解了,要么关闭透明大页面功能,这需要评估关闭后对其他应用的影响;要么暂时停掉那些使用了很多大页面的进程,重启使用dpdk的进程后,再启动它们(这不是一个好的解法);要么为系统分配更多的大页面;要么使用dpdk的进程通过-m申请更少的大页面。

在有透明大页面功能的操作系统中,有个内核进程khugepaged,它也会定期地回收大页面,整理大页面。

关闭透明大页面的方法:

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

  

本文所有的讨论和解法,都是基于dpdk-16.07,更新或更旧的版本是否有这个问题,是否也能这么解,不得而知。

DPDK无法分出连续大页面(contiguous hugepages)的几个解决方法的更多相关文章

  1. DPDK无法分出大页面:EAL: No free hugepages reported in hugepages-2048kB 解决方法

    参考: [dpdk-users] Fw: DPDK Error --> EAL: No free hugepages reported in hugepages-2048kB DPDK无法分出连 ...

  2. eclipse中的出现在打包一次后,后面新建的项目都出错了,出现support_v7下面出现红线及解决方法及为什么eclipse中项目继承ActionBarActivity解决方法一样

    第一次写博客,有什么问题或者想法的希望各位可以进行评论交流,望大家多多包涵! 遇到的问题是在新建的项目都出错了,出现support_v7下面出现红线及解决方法及为什么eclipse中项目继承Actio ...

  3. ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法

    在IE9,或IE10中ckfinder在IE10,IE9中的弹出框不能选择,或者不能上传解决方法   把弹出框嵌入到jquery dialog中.可以解决 I did: // javascript f ...

  4. Eclipse 新建.jsp页面后,页面头部标签报错的解决方法

    Eclipse 新建.jsp页面后,页面头部标签报错的解决方法 1.报错地方: 2.解决方法: .jsp页面右键==>BUild Path ==>Configure Build Path. ...

  5. 页面按F5重复提交数据解决方法

    在Web开发中,必须面对的问题就是表单的重复提交问题(这里仅指F5刷新造成的重复提交),.NET中处理这个问题似乎没有什么好的方法. 在网上搜索得到的解决方法主要有两种,一种是直接让表单按钮失效,从而 ...

  6. 2、vuex页面刷新数据不保留,解决方法(转)

    今天这个问题又跟页面的刷新有一定的关系,虽然说跟页面刷新的关系不大,但确实页面刷新引起的这一个问题. 场景: VueX里存储了 this.$store.state.PV这样一个变量,这个变量是在app ...

  7. bootstrap弹出模态框会给body加padding的解决方法

    bootstrap弹出模态框会给body加padding,导致页面缩放的解决方法: 在页面或是css文件里加上($paddingSize为less变量,需要改成像素或是其他单位,如12px,1rem) ...

  8. 页面渲染时js阻塞的解决方法

    一般地,一个包含外部样式表文件和外部脚本文件的HTML载入和渲染过程是这样的: 浏览器下载HTML文件并开始解析DOM. 遇到样式表文件link[rel=stylesheet]时,将其加入资源文件下载 ...

  9. 只有图片拼接的html页面图片之间有白条的解决方法

    有时候会有这样的页面,整个页面也就是几张切好的图片组成,但是把这些图片使用代码拼接好,又总会出现图片间有白条的问题,如下图: 解决方法:给图片的父容器添加 line-height: 0; 就好了,因为 ...

随机推荐

  1. 使用SetUnhandledExceptionFilter转储程序崩溃时内存DMP .

    关于程序崩溃时转储内存DMP,可以设置注册表,使程序崩溃时自动转储内存DMP,见程序崩溃时利用注册表自动转储内存DMP.本文要介绍的是使用SetUnhandledExceptionFilter函数在程 ...

  2. HTML中的转义字符 (转)

    HTML中<, >,&等有特殊含义,(前两个字符用于链接签,&用于转义),不能直接使用.使用这三个字符时,应使用它们的转义序列,如下所示: & 或 & &a ...

  3. 强制windows系统重启at命令

    at 02:00 /every:m,t,w,th,f,s,su shutdown -r -f -t 0

  4. 跨平台APP----对Cordova,APPCan,DCloud,APICloud四大平台的分析

    前言: 移动开发是未来一个很重要的IT领域,而跨平台开发将是这一领域最重要的事情.         ----谷震平 一 兵器谱 在国外,最大的是Cordova(PhoneGap,2011年广泛流行), ...

  5. TCP/UDP常见端口

    著名端口 端口号码 / 层 名称 注释 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat ...

  6. 实战HMM-Viterbi角色标注地名识别

    http://www.hankcs.com/nlp/ner/place-names-to-identify-actual-hmm-viterbi-role-labeling.html 命名实体识别(N ...

  7. Thinkphp5 使用odbc连接到sqlserver

    在PHP中访问mssql有两个方式 1.安装相应的驱动,如sqlsrv 2.直接使用PHP自带的ODBC驱动(不需要安装)   本文直接使用自带的ODBC驱动 在使用前请确定PHP开启了php_pdo ...

  8. Port already be taken

    我运行同一个docker run命令两次后,第二次给出提示,说端口已经被占用. Port has already been allocated [解决方法] 运行docker container ls ...

  9. [Javascript] Avoiding Mutations in JavaScript with Immutable Data Structures

    To demonstrate the difference between mutability and immutability, imagine taking a drink from a gla ...

  10. AI单挑Dota 2世界冠军:被电脑虐哭……

    OpenAI的机器人刚刚在 Dota2 1v1 比赛中战胜了人类顶级职业玩家 Denti.以建设安全的通用人工智能为己任的 OpenAI,通过“Self-Play”的方式,从零开始训练出了这个机器人. ...