linux 减小缓存,如何从内核空间中缩小Linux页面缓存?

我正在研究一个涉及一些自定义硬件和我为硬件编写的自定义Linux设备驱动程序的系统.系统偶尔需要非常快速地移动大量数据,因此我的驱动程序动态地(即在需要时)分配大的(1 GB)DMA缓冲区,这些缓冲区被使用,然后在不再需要时释放.为了分配这么大的缓冲区,我实际上使用dma_alloc_coherent分配了一堆较小的缓冲区(256 X 4MB),然后使用remap_pfn_range将它们连续映射到用户空间.这在大多数情况下非常有效.

在测试期间,在系统长时间运行测试用例之后,我有时会看到DMA分配失败,其中我的驱动程序中的一个dma_alloc_coherent调用失败,导致我的应用层软件崩溃.我终于能够找到这个问题,我发现当我看到DMA分配失败时,Linux内核页面缓存非常充分.

例如,在我捕获页面缓存的最后一次失败中,在我的系统上填充了27 GB的32 GB RAM.我怀疑页面缓存“fullness”导致dma_alloc_coherent调用失败.为了测试这个理论,我使用以下方法手动清空页面缓存:

# echo 1 > /proc/sys/vm/drop_caches

这将缓存的大小从27 GB减少到94 MB,并且我能够分配20个1 GB DMA缓冲区而没有任何问题.

很明显,页面缓存是一件有益的事情,所以在分配DMA缓冲区时,每次空间不足时,我都不希望完全清空它.我的问题是:如何动态缩小内核空间中的页面缓存,这样如果调用dma_alloc_coherent失败,我可以恢复足够的空间,以便我可以重试调用并使其成功?

我的系统是基于x86_64的,运行3.16.x Linux内核.

我发现了一些模糊的引用,表明我正在尝试的可能,例如“这些对象是自动的

在系统的其他地方需要内存时由内核回收.“(来自:https://www.kernel.org/doc/Documentation/sysctl/vm.txt).但我还没有找到任何指明内存如何回收的细节.

对此的任何帮助将不胜感激!

解决方法:

TL; DR:扫描活动超级块并删除对非脏块的引用,直到您根据需要回收了尽可能多的系统内存. (或者你最终用尽了对活动超级块的引用.)

How to write kernel code to dynamically shrink the fs page-cache,

to recover just enough space so that a subsequent call to dma_alloc_coherent() succeeds?

要回答这个问题,让我们看一下“drop_caches操作”在您的系统上将fs页面缓存从27GB减少到94MB的功能.

> echo 1>的/ proc / sys目录/ VM / drop_caches

所调用

drop_caches_sysctl_handler()

>反过来调用iterate_supers()和

将指针传递给函数drop_pagecache_sb().

接下来发生的事情是iterate_supers()扫描活动超级块,每次找到一个时,它调用drop_pagecache_sb(),向活动超级块传递一个引用.

该迭代过程继续,直到从fs页面高速缓存中释放对所有活动超级块的引用.这是一种非破坏性操作,只会释放完全未使用的块.脏对象将继续使用,直到写入磁盘并且不可用.如果先运行同步将它们刷新到磁盘,“drop_caches操作”往往会释放更多内存.

Since you are interested in running this process to reclaim a limited/known amount of memory i.e. what is soon going to be requested using dma_alloc_coherent(), you simply need to implement the above functionality with an additional check at the end of each iteration and abort the superblock scan immediately once the amount of free system memory crosses the desired level.

要记住以下几点,以进一步优化此过程:

>某些块设备是否优先于其他块设备?

您可能希望首先迭代您不关心的块设备的活动超级块.如果没有回收足够的内存,则扫描您希望保留在fs页面缓存中的块设备,除非绝对需要回收所需的内存. get_active_super()可能在这里有所帮助.

> iterate_supers_type()似乎很有趣

它允许一个迭代特定file_system_type的超级块

请注意,这是一个推测性解决方案,完全基于您已经观察到已经解决问题的Linux内核中现有代码的分析.一旦实现了上述方法,它将只允许您控制相同的操作,即仅尝试回收fs页面缓存内存,仅满足您的即时需求.

标签:memory-management,linux,linux-kernel,linux-device-driver

来源: https://codeday.me/bug/20190611/1221940.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值