源文件编译、链接后得到可执行的文件。
程序加载至内存后,就会创建一个进程task_struct,即进程的描述符,进程的描述符由内核维护。
task_struct中包含指向mm_struct的成员,它包括了内存管理相关的信息。
mm_struct涉及了物理内存管理和虚拟内存管理的部分,物理内存管理的就是进程的页表,虚拟内存管理的就是vm_area_struct的多个实例构成的红黑树结构。
task_struct中当然还有文件相关的file对象的数组,描述进程打开的文件,网络套接字也算在内。
进程的页表的作用是完成线性虚拟地址到物理地址的转换用的,vm_area_struct主要是完成可执行文件到线性虚拟地址的转换用的,包括了当前可执行文件、动态共享库的加载路径和所占的虚拟地址空间。
程序中的代码区中的指令都是基于虚拟地址空间的,在源文件中看到的分配动态地址空间都是虚拟地址空间,也就是通过vm_area_struct表示。
CPU在通过PC程序计数器执行程序的时候,通过MMU完成虚拟地址到物理地址的转换,这些虚拟地址包括代码区中的指令以及符号引用,这个时候需要借助进程的页表的映射,如果在执行时物理内存没有分配,就会触发缺页中断,内核分配物理内存,这个时候就会更新页表和vm_area_struct,也就是在此时才完成真正的物理内存的分配和映射。
CPU在执行过程中会涉及函数栈的操作和向堆申请动态内存的操作,也就是用户地址空间(0~3G)上端的栈区和用户地址空间中段的堆内存区。如果还要执行系统调用的话,还要到内核空间(3G~4G)中的栈中去执行。
mmu可能还控制着可执行文件的内存布局模式(2+2,3+1)
就像说java虚拟机中的所有线程共享代码区和常量池一样,linux下的所有进程也要共享一些寄存器,如PC程序计数器,PS程序状态字等。linux的所有进程还要共享(3g~4g)内核地址空间。
进程在进行切换时,需要保存当前进程的一些上下文信息,常见的就是堆栈,寄存器的值等,这些上下文都是内核维护的。调度器scheduler完成调度时,需要将新的进程的上下文导入到通用寄存器中,因为这些寄存器只有一套,大家共享使用。
阅读(2073) | 评论(0) | 转发(0) |