注意,对于内核中配置为 CONFIG_MMU_LAZY_TLB_REFCOUNT=n 的系统,mm_count 引用计数可能不再包括“懒惰”用户(即运行任务时满足条件 ->active_mm == mm && ->mm == NULL 的用户)。必须使用 mmgrab_lazy_tlb() 和 mmdrop_lazy_tlb() 辅助函数来获取和释放这些懒惰引用,这些函数会对这个配置选项进行抽象处理。
列表:linux-kernel
主题:Re: active_mm
发件人:Linus Torvalds <torvalds () transmeta ! com>
日期:1999-07-30 21:36:24
抄送给 linux-kernel,因为我并不经常写解释,但当我这样做时,希望更多的人能够阅读。
在 1999 年 7 月 30 日,David Mosberger 写道:
有没有一个简要的描述,说明了在 task_struct 中的“mm”和“active_mm”应该如何使用?(如果这在邮件列表上已经讨论过,我很抱歉,因为我刚从度假回来,一段时间内无法关注 linux-kernel。)
基本上,新的设置如下:
- 我们有“真实地址空间”和“匿名地址空间”。不同之处在于匿名地址空间根本不关心用户级页表,因此当我们切换到匿名地址空间时,我们只需保持之前的地址空间处于活动状态。
“匿名地址空间”的明显用途是任何不需要任何用户映射的线程——所有内核线程基本上都属于这一类别,但即使“真实”线程也可以暂时表示在一段时间内不会对用户空间感兴趣,并且调度程序可能会尽量避免在切换 VM 状态时浪费时间。目前只有旧式的 bdflush 同步执行这一点。 - “tsk->mm”指向“真实地址空间”。对于匿名进程,tsk->mm 将为 NULL,这是合乎逻辑的,因为匿名进程根本就没有真实地址空间。
- 然而,我们显然需要跟踪为这样的匿名用户“窃取”的地址空间。为此,我们有“tsk->active_mm”,它显示当前活动的地址空间是什么。
规则是,对于具有真实地址空间的进程(即 tsk->mm 非 NULL),active_mm 显然必须始终与真实地址空间相同。
对于匿名进程,tsk->mm == NULL,而 tsk->active_mm 是匿名进程运行时“借用”的 mm。当匿名进程被调度走时,借用的地址空间将被归还并清除。
为了支持所有这些,现在“struct mm_struct”有两个计数器:一个是“mm_users”计数器,表示有多少“真实地址空间用户”,另一个是“mm_count”计数器,表示有多少“懒惰”用户(即匿名用户),如果有任何真实用户,则加一。
通常至少有一个真实用户,但可能会出现这样的情况:真实用户在另一个 CPU 上退出,而懒惰用户仍然活跃,因此实际上可能存在一个仅由懒惰用户使用的地址空间。这通常是一个短暂的状态,因为一旦该线程被调度以优先于真实线程,由于“mm_count”变为零,这个“僵尸”mm将被释放。
另外,一个新规则是,_没有人_再将“init_mm”视为真实的 MM。应该将“init_mm”视为“没有其他上下文可用时的懒惰上下文”,实际上它主要只在启动时使用,因为尚未创建真正的虚拟内存。因此,以前用于检查
if (current->mm == &init_mm)
通常应该改为
if (!current->mm)
(这更有意义——测试基本上是“我们是否有用户上下文”,通常由页面错误处理程序等部分执行。)
无论如何,我刚刚在 ftp.kernel.org 上发布了一个预补丁-2.3.13-1,因为它稍微改变了接口以适应 alpha(谁会想到,但 alpha 实际上最终拥有了最丑陋的上下文切换代码——与其他架构不同,alpha PALcode 将 MM 和寄存器状态合并在一起,因此需要同时切换两者)。