目录
- 上层用户看到的地址
- 父进程创建子进程对代码区的同一变量修改
- 进程地址空间
- 进程地址空间需要划分
- 页表
上层用户看到的地址
一个系统中的进程是与其他进程共享内存和CPU的。如果某个进程不小心写入另一个使用该内存的进程,进程就可能以某种完全和程序逻辑无关的方式运行,造成进程崩溃。
父进程创建子进程对代码区的同一变量修改
父进程创建子进程,刚开始子进程要继承父进程的代码和数据,没有其他的代码和数据。父进程的资源都是给子进程共享的。我们发现父子进程对同一变量num进行不一样的操作,且相互不影响,因为进程是相互独立的,但是取地址发现他们的地址变量是一致的。着就说明了父子进程对应的全局num的取地址变量不是真实的物理地址,是虚拟的地址。这是因为父进程创建子进程的时候,拷贝了父进程的一个表,叫进程地址空间。因为是拷贝的,所以他们虚拟地址一样,上层用户看到同样的地址,实际上,进程还要通过一个叫页表的表来映射虚拟地址和物理内存的关系,一旦父子进程对数据有修改的操作,操作系统会为第一个改变数据的进程在物理地址重新找到一个可以使用的物理内存,改变页表的映射关系。这样进程就保证了独立性。
页表映射到物理内存是随机的。不会在意分别的规则。
进程地址空间
栈向下使用,堆向上使用
上述图片不是进程的内存,是保存了进程的代码和数据的地址的一张线性表,从下往上增加,都是地址数据。这是为了有效管理主存的一个抽象概念。当程序运行的时候,程序的代码和数据在进程中其实已经被编译成为一系列的指令地址来对应代码和数据。进程地址空间有效的对物理内存进行了保护。在Linux系统的虚拟内存就是上图组织的,系统为每个进程创建这样的一个虚拟内存。计算机通过虚拟内存加偏移量来寻找内存位置。
进程地址空间需要划分
进程需要被描述成一个task_struct结构体对象,并以一定的数据结构来对进程进行管理,进程地址空间也应该如此,Linux进程地址空间其实就是进程task_struct结构体的一个对象,叫mm_struct。
引用深入理解计算机系统
struct task_struct {//进程控制块//....................//....................struct mm_struct *mm, *active_mm;//....................
}
struct mm_struct {//进程地址空间struct vm_area_struct * mmap;
}
struct vm_area_struct {//进程地址空间的划分struct mm_struct * vm_mm; /* The address space we belong to. *///属于哪个进程地址空间unsigned long vm_start; /* Our start address within vm_mm. *///起始位置unsigned long vm_end; /* The first byte after our end addresswithin vm_mm. *///结束位置的第一个字节/* linked list of VM areas per task, sorted by address */struct vm_area_struct *vm_next;//链表结构组织
}
vm_area_struct结构体会对进程地址进行划分,如果计算机为32位,进程地址空间就会有4GB,vm_area_struct会对这4GB空间大小进行划分。划分是为了更好的管理内存,把有序的进程地址空间通过页表映射的方式找到无序物理内存。更好的管理内存空间。更安全的使用内存。进程管理和内存管理解耦。
得出结论:进程地址空间被描述为一个结构体对象,是进程task_struct的一个对象,然后以链表形式组织起来。
页表
页表存在于物理内存的一个页表条目数组(Page Table Entry,PTE),页表的作用是让物理内存和虚拟地址有映射的关系。 每个进程都有自己的独立页表,且页表不仅仅只是一份。虚拟内存地址和物理内存地址之间需要一个叫MMU(内存管理单元)的硬件进行翻译。每个页表都有一个标记为,标记为位0或1,如果位1,表示虚拟内存有映射到物理内存的关系是否存在。一个进程有一个一级页表和可能多个的二级页表。在一个32位的计算机当中,在32个bit位当中,前10个bit位做为一级页表的映射关系,但一级页表不映射到物理内存,映射到二级页表当中,10个bit位可以映射1024个二级页表,然后二级页表用继续用10个bit位计算,就可以映射到物理地址,每个二级页表也可以映射1024个物理地址空间,然后1024个二级页表一起就可以映射到1024 * 1024 个物理地址空间。在物理内存当中,以4GB
的为例,内存会以4KB位大小的页框来划分该物理内存。就会有1024*1024个页框。后12位的bit则表示的是偏移量。