diff -u:内核开发的新特性

作者: Zack Brown

OOM killer 是个难啃的硬骨头。当系统剧烈抖动并耗尽 RAM 时,如何才能恢复? 曾经,你只需要重启。 而今天,虽然可能仍然需要重启,但必要性降低了,因为 OOM killer 尝试识别并停止似乎导致系统挂起的进程。 问题是,它可能并非每次都选择正确的进程。 另一个问题是,整个事情非常棘手且复杂。

Michal Hocko 最近尝试剥离出一小部分进行研究,借鉴了 Mel GormanOleg Nesterov 的思路。 显然,当前的 OOM killer 会为它想要杀死的进程分配额外的内存,以便实际上给它足够的喘息空间来正常终止。 但在某些情况下,进程会接受额外的内存,但仍然会挂起系统。 然后,由于没有更多内存可分配,OOM killer 无法再次尝试,就只能按下复位按钮了。

Michal 发布了一个补丁,用于创建一个新的内核线程,如果额外的内存未被使用,该线程将回收这些内存。 这样,OOM killer 就可以在不同的进程上尝试相同的事情,并有望获得不同的结果。 尽管没有人对 Michal 的补丁本身提出重大异议,但许多人反对对 OOM killer 进行任何形式的渐进式改进的想法,因为“大问题”尚未解决。

正如 Johannes Weiner 所描述的,“大问题”是如何从根本上解决内存死锁。 只有解决了这个问题,OOM killer 才能成功杀死它需要杀死的进程,甚至达到杀死所有用户进程的地步,只是为了保持内核运行。

但是,Michal 坚持将讨论范围限定在他提出的那些小修补程序上。 他承认自己没有解决“大问题”的方案,并指出似乎也没有其他人对“大问题”有可行的解决方案。 在出现可行的方案之前,Michal 认为拖延 OOM killer 的开发毫无意义。 他认为,如果有什么可以改进它的,就应该去做。

总的来说,大家都同意了这一点,但很明显,OOM killer 系统面临着很大的压力,需要提出某种新想法,或者至少创建一个基于策略的系统,将杀死进程的选择权交给系统管理员,而不是内核算法本身。

Linus Torvalds 对任何编写需要锁定资源的内核代码的人提出了一些建议:最好使用现有的锁定实现,而不是自己编写,至少在你了解自己在做什么之前是这样。 他说

人们需要意识到锁定比他们想象的要困难,不要在没有真正深入思考的情况下,使用像 trylock 这样的东西来 concoct (cook up) 他们自己的锁原语。

基本上,trylock() 本身绝不应该在循环中使用。 trylock 的主要用途应该是以下之一

1) 如果无法获取锁,则完全不执行的操作。

2) 避免 ABBA 死锁:如果你有一个 A->B 的锁定顺序,但你已经持有 B,与其“先释放 B,然后按正确的顺序获取 A 和 B”,你可能首先决定 trylock(A),如果失败,你再退回到“释放并按正确的顺序重新锁定”。

但是,如果你想创建的是“使用 trylock 获取锁”,你至少需要非常清楚缓存一致性流量问题。

我们或许应该考虑尝试为 loop_try_lock() 引入一个新的原语。 但这可能不够常见,不值得这样做——我们以前也遇到过这个问题,但我认为这是一种“每隔几年发生一次”的事情,而不是我们需要担心的事情。

“锁定很难”这个问题确实存在。 传统上,我们有很多代码试图自己实现锁定,但内存排序等方面做得不对。 有些东西在 x86 上可以工作,但在其他架构上却不行,等等。

Zack Brown 是 Linux JournalLinux Magazine 的科技记者,曾是 “Kernel Traffic” 每周新闻通讯和 “Learn Plover” 速记打字教程的作者。 他于 1993 年在他的 386 电脑上安装了 Slackware Linux,配备了 8 兆 RAM 内存,并被开源社区彻底震撼。 他是 Crumble 纯策略棋盘游戏的发明者,你可以用几块纸板自己制作。 他还喜欢写小说、尝试动画、改革拉班舞谱、设计和缝制自己的衣服、学习法语以及与朋友和家人共度时光。

加载 Disqus 评论