linux内核中的active_mm的作用

来源:互联网 发布:js.10000网上营业厅 编辑:程序博客网 时间:2024/05/19 12:25

linux内核中每个进程的task_struct中有两个关于描述内存映射的结构:mm和active_mm,之前一直没明白这两者的区别,今天google了一下,看到了Linus本人对引入active_mm的解释。发现其引入的原因和anonymous process有关,anonymous process我感觉就是我们常说的内核线程(ps输出中CMD名称带方括号的)。看完Linus的解释后,刚好又看到Robert Love对这个问题的解释,有了两位大师的解释,我这个菜鸟才如梦初醒。List:       linux-kernelSubject:    Re: active_mmFrom:       Linus Torvalds <torvalds () transmeta ! com>Date:       1999-07-30 21:36:24Cc'd to linux-kernel, because I don't write explanations all that often,and when I do I feel better about more people reading them.On Fri, 30 Jul 1999, David Mosberger wrote:>> Is there a brief description someplace on how "mm" vs. "active_mm" in> the task_struct are supposed to be used?  (My apologies if this was> discussed on the mailing lists---I just returned from vacation and> wasn't able to follow linux-kernel for a while).Basically, the new setup is: - we have "real address spaces" and "anonymous address spaces". The   difference is that an anonymous address space doesn't care about the   user-level page tables at all, so when we do a context switch into an   anonymous address space we just leave the previous address space   active.   The obvious use for a "anonymous address space" is any thread that   doesn't need any user mappings - all kernel threads basically fall into   this category, but even "real" threads can temporarily say that for   some amount of time they are not going to be interested in user space,   and that the scheduler might as well try to avoid wasting time on   switching the VM state around. Currently only the old-style bdflush   sync does that. - "tsk->mm" points to the "real address space". For an anonymous process,   tsk->mm will be NULL, for the logical reason that an anonymous process   really doesn't _have_ a real address space at all. - however, we obviously need to keep track of which address space we   "stole" for such an anonymous user. For that, we have "tsk->active_mm",   which shows what the currently active address space is.   The rule is that for a process with a real address space (ie tsk->mm is   non-NULL) the active_mm obviously always has to be the same as the real   one.   For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the   "borrowed" mm while the anonymous process is running. When the   anonymous process gets scheduled away, the borrowed address space is   returned and cleared.To support all that, the "struct mm_struct" now has two counters: a"mm_users" counter that is how many "real address space users" there are,and a "mm_count" counter that is the number of "lazy" users (ie anonymoususers) plus one if there are any real users.Usually there is at least one real user, but it could be that the realuser exited on another CPU while a lazy user was still active, so you doactually get cases where you have a address space that is _only_ used bylazy users. That is often a short-lived state, because once that threadgets scheduled away in favour of a real thread, the "zombie" mm getsreleased because "mm_users" becomes zero.Also, a new rule is that _nobody_ ever has "init_mm" as a real MM anymore. "init_mm" should be considered just a "lazy context when no othercontext is available", and in fact it is mainly used just at bootup whenno real VM has yet been created. So code that used to checkif (current->mm == &init_mm)should generally just doif (!current->mm)instead (which makes more sense anyway - the test is basically one of "dowe have a user context", and is generally done by the page fault handlerand things like that).Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,because it slightly changes the interfaces to accommodate the alpha (whowould have thought it, but the alpha actually ends up having one of theugliest context switch codes - unlike the other architectures where the MMand register state is separate, the alpha PALcode joins the two, and youneed to switch both together).On Wed, 2003-04-23 at 16:41, Bryan K. wrote:
> Reading the kernel source I have noticed that a kernel thread must always 
> have a valid mm_struct pointer at task_struct->active_mm. This prevents the 
> mm_struct to be deallocated if a kernel thread uses it. I was wandering why 
> a kernel thread need a mm_struct if it is not supposed to access addresses 
> below TASK_SIZE?

It does not need (or have) an mm_struct. task->mm is NULL in a kernel
thread (task->mm == NULL is what a kernel thread is, by definition, in
fact).

task->active_mm is just the current address space that is mapped in. It
is an optimization, so we can have something like:

task A is running and has an mm_struct of foo, thus
A->mm == A->active_mm == foo

task A is preempted by a kernel thread, B. Thus,
B->mm == NULL and A->active_mm == foo,
since the mm_struct was never replaced.

Now, if task A is rescheduled the mm need not be reloaded.

Make sense?

Robert Love
但看完Robert Love的解答后,我的疑惑又变为为啥kernel thread不需要memory address space?接着我又看到了Mulyadi的回答:kernel thread不要它自己的memory addreass space的原因是所有进程关于内核地址的映射都是一样的,内核线程可以使用任何进程的memory address space。
Hello Roy> I fail to understand the difference between task->mm and> task->active_mm. I've noticed that upon forking a task, both mm and> active_mm get the same memory descriptor.Well, here is my understanding. task_struct->mm points to memory descriptor which is unique to each process (unless they are on the same thread group, forked with CLONE_VM). active_mm points to the *actual* memory descriptor used by the process when it is executed.So why it is separated? IMHO the reason is to identify which process is kernel thread (doesn't own a process address space) and which one is normal process (owns a process address space). As you can see on functions related with context switching, by checking task_struct->mm, the scheduler can decide whether it is going to switch onto kernel thread or not. if it is NULL, then the process doesn't have process address space, in other word this is a kernel thread. But you also aware that even kernel threads don't acess user space memory, it still needs to access kernel space. because kernel space is 100% identical for every process, kernel thread can freely use memory descriptor (mm) owned by previously running process. All the kernel thread needed is page tables referencing toward virtual address bigger than PAGE_OFFSET, other are simply ignored by it is assumed that kernel thread doesn't need to access user space (perhaps it is somehow can be abused?)Hope it helps answering your questionregardsMulyadi
References:
http://www.cnblogs.com/Rofael/archive/2013/04/13/3019153.html
https://www.kernel.org/doc/Documentation/vm/active_mm.txt
http://blog.csdn.net/u012036443/article/details/14000151
原创粉丝点击