编译、链接学习笔记(四)进程装载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013230511/article/details/78010034

1.程序与进程的区别

程序是指计算机可执行文件在磁盘中的保存方式,他是一对预编译好的指令和数据的集合文件。而进程是计算机将程序按照一定规则运行程序的一个过程。两者相比程序是一个静态的概念,进程是一个动态的概念。

2.虚拟地址空间

每个进程运行起来后,操作系统为其分配了进程独立拥有的虚拟地址空间(Virtual Address Space)。这空间的大小是由计算机操作系统以及CPU的位数共同决定。CPU的物理属性决定了空间的最大值,除此外操作系统也会决定其访问的空间的权限等。

在操作系统来看,我们知道一个计算机的物理内存其实是有限的,而且操作系统层面上看还要支持多个进程的并发运行。操作系统并不会真的分配实际大小的内存空间,只是在给进程一个假象,让进程看起来拥有非常大空间,实际情况是操作系统才切换进行以及分配时间片运行进程时会让进程“看起来”拥有一段连续且非常大的内存空间。

如果从C程序的角度而言,最简单的可从指针的位数来看地址的空间大小,在32位机器下,指针的长度也为4字节,也便是32位,在64位机器下,指针长度为8个字节,也便是64位。

2.1 并非所有虚拟地址都可以访问

进程虚拟地址空间都是在操作系统的操作之下,并非所有的地址空间都可以访问,进行只能使用由操作系统分配的进行的地址。如访问非操作系统的内存空间,操作系统将会强制结束进程。windows下会遇到“进行因非法操作需要关闭”,linux下出现”Segmentation Fault”,Mac OS 会发生”EXE_BAD_ACCESS”。

如下是32位系统下,linux下的进程虚拟空间地址,默认情况下操作系统会将4G内存中最后的1G内存作为操作系统保留的内存地址。其他的地址给予进行操作。

这里写图片描述

3.程序装载到进程

将程序加载到进程才能正常使用。将程序加载到进程中最简单的方法是全部加载到内存中,但是操作系统层面并不太现实,在正常的的情况下所需要的内存大小都大于物理内存的大小。根据计算机运行的原则,进程的运行是由局部性原理。根据这个原理可以在程序使用到哪个模块时再载入内存,如果没使用到就暂时不装入。

3.1 页映射

根据程序的局部性原理,将程序进行模块的分块,在操作系统的控制下当进程使用到某个模块时再进行载入。
操作系统人为的将地址空间以“页(Page)”为单位进行切割,将程序等分成固定大小的页,操作系统的所有的装载和操作的单位就是页。
最常见的使用4K(4096字节)的页。

3.2 页错误

当需要使用一个指定的页,而页不在内存时,称为“页错误(Page Fault)”。虚拟内存空间与物理内存的映射是通过页错误驱动进行页的加载。
当程序执行发生页错误时,操作系统将物理内存中分配一个物理页,然后将“缺页”从磁盘加载到内存中,再设置缺页的虚拟页与物理页的映射关系,这样程序才得以运行。

这里写图片描述

3.2 进程的建立

一个程序的执行一般伴随这个一个进程的建立。进程的建立一般伴随着下面三件事情:
1.创建一个独立的虚拟空间
2.读取可执行文件头,建立虚拟内存空间和可执行文件的映射关系
3.指令寄存器指向可执行文件的入口地址,运行程序

3.2.1 创建独立的虚拟内存空间

操作系统为进程创建独立的虚拟内存空间,实际的操作是为进程分配一个页目录(Page Directory),以及为创建映射函数所需要的数据结构。

3.2.2 读取可执行文件头,建立虚拟空间与可执行文件的映射关系

当程序运行时,一旦发生缺页,则需要依赖一套映射规则,将可执行文件的页映射到虚拟内存。此步骤则是建立虚拟内存和可执行文件的映射规则。

3.2.3 指令寄存器指向可执行文件的入口,开始执行

操作系统通过将指令寄存器指向可执行文件的入口,将控制器交由进程。

没有更多推荐了,返回首页