我们用户程序在经过编译器编译之后所产生的那些地址都是虚拟地址,所存放的地方就叫做虚拟存储器概念上而言,虚拟存储器被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组,每字节都有一个虚拟地址。虚拟存储器又被分割成为了一些固定大小的块,这些块就叫做虚拟页,在任意时刻,虚拟页都分为三个状态集:未分配的,缓存的,未缓存的。
接下来我们讲讲进程的用户空间,它主要是由两个数据结构来描述的,一个是mm_struct,另一个是vm_area_struct。
1、mm_struct结构
它用来描述一个进程的虚拟地址空间,在内核中的定义如下(内核版本为2.6.32):- struct mm_struct{
- struct vm_area_struct *mmap;
- pgd_t *pgd;
- atomic_t mm_users;
- atomic_t mm_count;
- unsigned long start_code,end_code,start_data,end_data;
- unsigned long start_brk,brk,start_stack;
- .....
- .....
- };
上面代码在目录include/linux/mm_types.h中,上面只显示了部分代码。下面对主要域进行说明。
每个进程只有一个mm_struct结构,在每个进程的task_struct结构中,有一个指向该结构的指针,可以说,mm_struct结构是对整个用户空间的描述。那么,我们知道,每个可执行映像都有数据区与代码区等区域,可想而知,这都些都是包含在用户空间里的。我们使用vm_area_struct这个结构来描述这些区域。
2、vm_area_struct结构
这个结构用来描述进程用户空间的一个虚拟内存区间,代码部分定义如下:
- struct vm_area_atruct{
- struct mm_struct *vm_mm;
- unsigned long vm_start;
- unsigned long vm_end;
- struct vm_area_struct *vm_next;
- struct vm_operations_struct *vm_ops;
- unsigned long vm_pgoff;
- .....
- .....
- };
同样我们也对这个结构的一些比较重要的域进行说明:
那么为什么把进程的用户空间划分为一个个的区间?这是因为每个虚存区可能来源不同,有的可能来自可执行映像,有的可能来自共享库,有的可能来自动态分配的内存区,对不同的区间可能具有不同的访问权限,也有可能有不同的操作,因此,linux把进程的用户空间分割管理。一个完整的用户空间是在创建一个新进程的时候创建的。
3、虚存映射
随着进程的运行,内核会把文件从磁盘映射到进程的用户空间,这样把对文件的访问转换为对虚存区的访问,有两种类型的虚存映射:
1)、共享的:有几个进程共享这一映射,也就是说,如果一个进程对这个区域进行写操作,那么其他的进行也能感觉的到,而且会修改磁盘上对应的文件。
2)、私有的:对于每个映射私有对象的进程,相应的私有区域都被标记为只读,在这里linux采用了一种写时拷贝的技术,关于写时拷贝我们可以姑且先这么理解,就是使用到的时候才进行拷贝,否则就一直共享着这个区域。
除了上面的两种外,要是映射与文件无关,就叫做匿名映射。
在虚存映射这里我们还不得不提一个系统调用,就是mmap这个系统调用,因为我们的这些映射都是通过它来完成的,关于mmap这个系统调用的更具体的说明可以察看man手册。
下面这附图是描述了task_struct及mm_struct、vm_area_struct这三个结构的关系:
阅读(3720) | 评论(0) | 转发(0) |