我的理解是用户任务可以访问3G的用户空间和1G的内核空间。但是内核任务只能访问其仅有的 1G 内核空间。但是在task_struct中,它链接到指向用户空间的vm_area_struct,对吗?如果正确,那么这是否意味着内核任务也可以直接访问用户空间?
2 回答
用户任务只能访问低3G的用户空间(被映射的区域),内核可以访问所有的3G+1G空间。内核不直接访问用户空间地址,它使用 copy_from(to)_user() API。
以下来自 Robert Love 的 LKD3:mm_struct 和内核线程 (P309)
内核线程没有进程地址空间,因此没有关联的内存描述符。因此,内核线程的进程描述符的 mm 字段为 NULL。这是内核线程的定义——没有用户上下文的进程。
这种缺少地址空间的情况很好,因为内核线程从不访问任何用户空间内存。(他们会访问谁?)因为内核线程在用户空间中没有任何页面,所以它们不应该拥有自己的内存描述符和页表。(页表将在本章后面讨论。)尽管如此,内核线程需要一些数据,例如页表,甚至访问内核内存。为内核线程提供所需的数据,而不会将内存浪费在内存描述符和页表,或者在内核线程开始运行时浪费处理器周期切换到新的地址空间,内核线程使用之前运行的任何任务的内存描述符。
每当一个进程被调度时,该进程的 mm 字段引用的进程地址空间就会被加载。然后更新进程描述符中的 active_mm 字段以引用新的地址空间。内核线程没有地址空间, mm 为 NULL 。因此,当一个内核线程被调度时,内核注意到 mm 为 NULL 并保持前一个进程的地址空间加载。内核然后更新内核线程的进程描述符的 active_mm 字段以引用前一个进程的内存描述符。内核线程然后可以根据需要使用前一个进程的页表。因为内核线程不访问用户空间内存,所以它们只使用与内核内存相关的地址空间中的信息,这对于所有进程都是相同的。