9

Context Information In Memory Allocation Requests

 3 years ago
source link: https://kernel.taobao.org/2017/01/context-information-in-memory-allocation-requests/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Jan 1, 2017

Context Information In Memory Allocation Requests

本文要解决的是内核 api 设计在历史演进过程中的合理化问题。

大家都知道,内核的内存分配过程中,是要清楚的区分各种不同的情况的,例如:是否内存分配过程中会引起进程切换,大部分的驱动代码的中断处理函数中(面试中常问的问题,为什么中断上下文不能发生进程切换?)。所以,linux 内核的做法一直以来也就和我们大多数人在设计 api 的时候一样,即:加个 flag 吧,于是å核的内存分配函数变成下面的情况:

void *kmalloc(size_t size, gfp_t flags);

具体多少 flag, 看 <linux/gfp.h> 吧,处理内存分配中要区别处理的种种问题(这里面显然有些问题是 common 的,有些是 by design ç)

现在考虑下面三种情况:

  1. 当调用栈足够深的时候(内存分配 api 被多层封装):

Amalloc(…, flags) -> Bmalloc (…, flags) -> Cmalloc (…, flags) -> ………………. -> kmalloc(…, flags)

  1. 当调用在某个上下文频繁多次的时候:

kmalloc(…, flags) … kmalloc(…, flags) … kmalloc(…, flags) …

  1. 当底层调用需要修改 flags 的时候:

Amalloc (…, flags) -> kmalloc(…, new_flags) (比如:判断自己的上下文发生变化了ï¼

我们看到了什么?很多重复的 flags 出现在连续的 api 调用里,还有就是上层 flags 未必能完全决定底层 flags, 显然功能都 ok 了,只是过了 n 年之后,现在的开发者觉得太 ugly 了。

解决方法?大概就是很直观的:

  1. 拿掉 API 里面的这些 flags (或者提供新的 api 来过渡) 2. 最底层分配函数处理的时候,通过访问某个全局的信息来拿到这个 flags 或者根据具体情况来调整这个 flags, 全部由åº层调用决定

1 很简单了,2 这个全局的信息存哪呢,社区给出的部分做法是 task_struck 里面了,当然这个没问题,可以解决掉很多进程上下文的内存分配 flags 冗余问题(暂且就叫 flags 冗余吧),这应该是大头,因为在中断上下文中内存分配显然要简化很多,不过依然存在上述问题。

目前内核中给出了相应做法的例子:

PF_MEMALLOC_NOFS ==> task_struct -> flags

memalloc_nofs_save

… 这里面的内存å配,默认相当于增加 GFP_NOFS …

memalloc_nofs_restore

目前解决方法存在的问题:

  1. 我个人认为这也不是一个通用的方法,因为 flags 实在很多(就像我上面提到的有些是 common 的,有些是 by design ç),如果都这样单独处理难道不就是用另外一种复杂度替换之? 2. 历史问题太久远,很多已有的 callers (users) 依然需要支持,或者在很长一段时间内两种 api 要并存。 3. 并没有解决中断上下文的冗余问题

本文原作者提出了这样一个问题,也给出了一些解决方法,不过依然不完整,希望有兴趣的同学继续跟进内核社区在此处的进展,或者有更好的主意,也不妨自己改改。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK