前序: 磁盘,flash等都属于外存;主存可以理解为内存,cpu访问的是主存中的数据。
c语言或其他语言的源代码文件存在于磁盘上,由其经过gcc编译成的可执行文件也存在于磁盘,该可执行文件是无法直接交由cpu执行的, 一个可执行文件要发挥其作用,首先是把自己从外存加载(过程很复杂,其中包含了很多细节,不详说)到主存当中一份, 从磁盘中的一份程序文件变成了内存中的一个进程对应的虚拟内存区域。
该虚拟地址空间是由操作系统抽象(分页机制) 出的一个抽象层,供程序员读取,因为程序员直接对物理内存(物理内存即主机中的内存条)进行操作十分困难且麻烦,编码调试也十分不易, 所以操作系统会映射一个虚拟地址空间,起到一个中间桥梁作用,cpu访问物理内存,程序员访问虚拟内存,而虚拟内存由操作系统从物理内存映射出,这样连接贯通,如下图:
32位系统的虚拟内存大小是4GB(内存编码的基本单位是字节,2^ 32字节,转化单位即为4GB)虚拟内存的空间划分是根据进程号来划分区域,即每打开一个进程,虚拟内存就会分配一个区域给该进程,每一个进程都独享划分出的一份4GB内存区域。
例如X86 linux的默认情况下被划分成一比三的内核空间与用户空间,内核空间由多个进程共享(由于每一个虚拟进程都会占据一定量的物理内存空间,没必要每一份进程都向物理内存中装载一个内核,多个进程共享内核,起到节省资源的作用,与此相似的还有一个glibc动态链接库。) 。见下图(VM1为一个进程,VM2为一个进程,VM3为一个进程。一比三意思为Kernel:VM为一比三,Kernel+VM1为一个4GB内存区域,Kernel+VM2为一个4GB内存区域,Kernel+VM3为一个4GB内存区域)
对于一个4GB虚拟内存区域个结构图如下,最上方的kernel 内核空间是所有虚拟内存共享的。
对于windows,linux等操作系统,实际上是一个操作系统内核。内核外边套着用户程序,这样才成为一个操作系统。一个gnu的软件加上linux操作系统内核称为gnu linux操作系统。终端里各种各样的命令行工具实际上不属于linux内核的,而是一套是由GNU协会开发的用户态的可执行程序,属于GNU,gnu的软件源由ARCH来完成一些新软件的安装与管理。KDE来部署一个具体的桌面环境,如下图。
操作系统的内核的核心作用是管理硬件 ,肩负着硬件管理作用的所有的代码都是由内核本体和内核上挂载的一些内核驱动来完成的,这些与硬件交互的代码是内核态代码运行在内核空间中,而KDE 都是跑在用户台的,以一个虚拟内存的形式被操作系统管理,并且占用一定的物理内存。
上面所述为32位系统, 32位虚拟内存结构与64位的虚拟内存结构如下图
code(text)与data段是由ELF 文件程序中加载过来的,内部还含有其他节,见下图,heap空间是用来满足用户动态内存申请需要的。 Memmory Mapping Region 空间大部分是用来映射一个外部文件或者外部数据,如glibc。 PWN的最经典,最常见,最高危的一类漏洞基本都出自于Stack这段区域。Stack区域的作用简单概括就是控制程序执行流,协助程序来完成程序流转移和恢复。Kernel space 区域是操作系统内核加载的一个空间。
静态存储区在进程运行的整个生命周期中都是不变的, 动态存储区(heap,Stack),Stack会随着函数的调用与返回不断地创建与销毁,heap会随着用户的内存申请会动态的分配与释放。
一个字(word)时两个字节(byte),双字(dword)是4个字节,四字(qword)是八个字节。
Comments | 1 条评论
博主 fanfan
看不懂