.. include:: ../disclaimer-zh_CN.rst

:Original: Documentation/mm/active_mm.rst

:翻译:

 司延腾 Yanteng Si <siyanteng@loongson.cn>

:校译:


=========
Active MM
=========

注意，在配置了 CONFIG_MMU_LAZY_TLB_REFCOUNT=n 的内核中，mm_count 引用计数
可能不再包括“懒惰”用户（运行任务中 ->active_mm == mm && ->mm == NULL）。
获取和释放这些懒惰引用必须使用 mmgrab_lazy_tlb() 和 mmdrop_lazy_tlb() 这
两个辅助函数，它们抽象了这个配置选项。

这是一封linux之父回复开发者的一封邮件，所以翻译时我尽量保持邮件格式的完整。

::

 List:       linux-kernel
 Subject:    Re: active_mm
 From:       Linus Torvalds <torvalds () transmeta ! com>
 Date:       1999-07-30 21:36:24

 因为我并不经常写解释，所以已经抄送到linux-kernel邮件列表，而当我做这些，
 且更多的人在阅读它们时，我觉得棒极了。

 1999年7月30日 星期五， David Mosberger 写道：
 >
 > 是否有一个简短的描述，说明task_struct中的
 >  "mm" 和 "active_mm"应该如何使用？ (如果
 > 这个问题在邮件列表中讨论过，我表示歉意--我刚
 > 刚度假回来，有一段时间没能关注linux-kernel了）。

 基本上，新的设定是：

  - 我们有“真实地址空间”和“匿名地址空间”。区别在于，匿名地址空间根本不关心用
    户级页表，所以当我们做上下文切换到匿名地址空间时，我们只是让以前的地址空间
    处于活动状态。

    一个“匿名地址空间”的明显用途是任何不需要任何用户映射的线程--所有的内核线
    程基本上都属于这一类，但即使是“真正的”线程也可以暂时说在一定时间内它们不
    会对用户空间感兴趣，调度器不妨试着避免在切换VM状态上浪费时间。目前只有老
    式的bdflush sync能做到这一点。

  - “tsk->mm” 指向 “真实地址空间”。对于一个匿名进程来说，tsk->mm将是NULL，
    其逻辑原因是匿名进程实际上根本就 “没有” 真正的地址空间。

  - 然而，我们显然需要跟踪我们为这样的匿名用户“偷用”了哪个地址空间。为此，我们
    有 “tsk->active_mm”，它显示了当前活动的地址空间是什么。

    规则是，对于一个有真实地址空间的进程（即tsk->mm是 non-NULL），active_mm
    显然必须与真实的mm相同。

    对于一个匿名进程，tsk->mm == NULL，而tsk->active_mm是匿名进程运行时
    “借用”的mm。当匿名进程被调度走时，借用的地址空间被返回并清除。

 为了支持所有这些，“struct mm_struct”现在有两个计数器：一个是 “mm_users”
 计数器，即有多少 “真正的地址空间用户”，另一个是 “mm_count”计数器，即 “lazy”
 用户（即匿名用户）的数量，如果有任何真正的用户，则加1。

 通常情况下，至少有一个真正的用户，但也可能是真正的用户在另一个CPU上退出，而
 一个lazy的用户仍在活动，所以你实际上得到的情况是，你有一个地址空间 **只**
 被lazy的用户使用。这通常是一个短暂的生命周期状态，因为一旦这个线程被安排给一
 个真正的线程，这个 “僵尸” mm就会被释放，因为 “mm_count”变成了零。

 另外，一个新的规则是，**没有人** 再把 “init_mm” 作为一个真正的MM了。
 “init_mm”应该被认为只是一个 “没有其他上下文时的lazy上下文”，事实上，它主
 要是在启动时使用，当时还没有真正的VM被创建。因此，用来检查的代码

   if (current->mm == &init_mm)

 一般来说，应该用

   if (!current->mm)

 取代上面的写法（这更有意义--测试基本上是 “我们是否有一个用户环境”，并且通常
 由缺页异常处理程序和类似的东西来完成）。

 总之，我刚才在ftp.kernel.org上放了一个pre-patch-2.3.13-1，因为它稍微改
 变了接口以适配alpha（谁会想到呢，但alpha体系结构上下文切换代码实际上最终是
 最丑陋的之一--不像其他架构的MM和寄存器状态是分开的，alpha的PALcode将两者
 连接起来，你需要同时切换两者）。

 (文档来源 http://marc.info/?l=linux-kernel&m=93337278602211&w=2)
