task_struct 结构,mm_struct 结构, vm_area_struct 结构
1、task_struct
每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。
- 位置:<include\linux\sched.h> - 593行
- 部分代码如下:
struct task_struct
{
/*...*/
struct mm_struct *mm;
struct mm_struct *active_mm;
/* Per-thread vma caching: */
struct vmacache vmacache;
/*...*/
}
-
*mm
mm为mm_struct类型的指针,指向mm_struct结构,对于普通的用户进程来说mm字段指向他的虚拟地址空间的用户空间部分,对于内核线程来说这部分为NULL。 -
*active_mm
对于匿名进程,也可以理解为内核线程,它的mm字段为NULL,表示没有内存地址空间,可也并不是真正的没有,这是因为所有进程关于内核的映射都是一样的,内核线程可以使用任意进程的地址空间。
内核schedule在进程上下文切换的时候,会根据task->mm判断即将调度的进程是用户进程还是内核线程。
由于内核线程之前可能是任何用户层进程在执行,故用户空间部分的内容本质上是随机的,内核线程决不能修改其内容,故将mm设置为NULL。所以对于内核线程来说task_struct->mm == NULL,而task_struct->active_mm为某个进程的mm。
如果切换出去的是用户进程,内核将原来进程的mm存放在新内核线程的active_mm中,因为某些时候内核必须知道用户空间当前包含了什么。
而当内核线程离开的时候,会把借用的地址空间将会返还给原来的进程,并且清除这一字段。 -
vmcacahe
vmacache结构体定义在<include\linux\mm_types_task.h>的34行,如下:#define VMACACHE_BITS 2 #define VMACACHE_SIZE (1U << VMACACHE_BITS) struct vmacache { u64 seqnum; struct vm_area_struct *vmas[VMACACHE_SIZE]; };
可以看到它是一个vm_area_struct类型的数组指针,表示指向几段vma。
这是由于为了提高vma的查找速度,由传统的链表式改为了红黑树管理,然而某些进程地址空间中的vma数量众多,而查找vma又是内核中非常频繁的操作,所以为了进一步加快查找速度,内核采取了一种缓存方式,就是把最近访问的几个vma保存起来。
VMACACHE_SIZE为左移2位的一个无符号整形数字,这里感觉大概是保存了4个最近访问的vma。
2、mm_struct
每一个进程都会有唯一的mm_struct结构体
- 位置:<include\linux\mm_types.h> - 340行
- 部分代码如下:
struct mm_struct
{
/*...*/
struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb;
u64 vmacache_seqnum; /* per-thread vmacache */
unsigned long mmap_base; /*映射基地址*/
unsigned long mmap_legacy_base; /*不是很明白这里*/
unsigned long task_size; /*该进程能够vma使用空间大小*/
unsigned long highest_vm_end; /*该进程能够使用的vma结束地址*/
pgd_t * pgd;
atomic_t mm_users;
atomic_t mm_count;
int map_count; /* vma的总个数 */
unsigned long total_vm; /* 映射的总页面数*/
/*...*/
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
/*...*/
-
*mmap
该进程内已经使用的进程虚拟空间vm_are_struct结构,以双链表形式存储该指针指向vma链表的头节点。 -
mm_rb
红黑树组织形式,用于快速查找。
rb_boot结构体定义在<include\linux\rbtree.h>的43行struct rb_root { struct rb_node *rb_node