一起来学内存(二)
来源:互联网 发布:linux python 编辑器 编辑:程序博客网 时间:2024/04/27 23:52
————————————–尊重原创,从我做起;分享知识,标明出处。————————————–
在上一篇的博文中,博主和大家一起理清了物理内存与虚拟内存的概念,并介绍了虚拟内存、物理内存的取址范围。在这里强烈建议,博友们先去看了上一篇“一起来学内存(一)”之后,再来看本篇博文,概念会更加清晰。
现在我们已经了解到,作为程序员,我们平常操作的内存地址都是虚拟内存的地址,该地址会由MMU映射称为物理内存地址。
那么平常我们经常听到的栈内存、堆内存究竟是什么呢?与虚拟内存和物理内存又有什么关系呢?
要想搞清楚这些复杂的概念,我们首先得理清程序与进程的关系。
这里博主以编译型语言C++、Linux操作系统为例,为大家讲一下整个程序运行的过程。
下图就是从C++源代码到可执行文件的全过程:
1.书写C++源代码 (hello.cpp)
#include<iostream> using std::cout; int main(){ cout<<"hello world"; return 0; }
2.将 .cpp源文件预处理为 .ii文件
注:若是 .c的源文件文件,应预处理为 .i文件
3.将 .ii文件生成 .s汇编文件
4.将 .s汇编文件生成 .o目标文件
5.将 .o目标文件链接需要的动态库或动态库生成 .out可执行文件
经过了这4步工作后,写好的.cpp文件终于变成了可执行程序了。
但是可执行程序(文件)又和进程有什么关系呢?
首先我们要搞清楚程序与进程的区别。
程序是一种静态的概念,而进程是一种动态的概念。进程是操作系统中能够竞争资源的最小单位。这些资源包括什么呢?当然就包括我们一直讨论的内存空间啦。
Linux系统下进程被分配的内存布局大体如下图所示:
栈区(Stack): 用来存放临时变量和一些函数参数等
堆区(Heap): 存放通过 new 或 malloc动态申请的变量,此块内存空间一般由程序员手动 delete或是 free
静态区(BSS Segment): 存放未被初始化的全局变量和静态变量
数据区(Data Segment): 存放被程序员初始化过的全局变量和静态变量
代码区(Text Segment): 存放可执行的二进制指令操作
所以我们平常所谈论的堆栈,其实是加载运行我们所写的可执行程序的进程所被分配的内存空间。
那么现在我们就来看看我们在执行可执行程序时,是如何将数据写入为进程分配的内存中去的。
以Linux 的BASH为例,我们会以shell 语句来执行上述生成的 a.out文件
Shell> ./a.out
- 当执行一个可执行文件时,shell父进程首先会调用fork()方法,生成一个子进程。这个新生成的进程也就是执行 a.out程序的进程。这里简单提一下fork()方法,当父进程通过fork()方法创建子进程时,子进程会复制父进程的页目录与页表。之后通过写时复制(copy on write)技术,子进程就能拥有独立的页目录项。
- 在新的进程创建出来后,它将拥有自己的PID和虚拟空间。这时已经切换到了新的进程执行execve系统调用,来加载可执行文件 a.out的头部信息,并为其建立新的页表结构。通过可执行文件的头部信息,系统就能建立进程的地址空间与可执行文件的映射关系。但此时新进程的进程地址空间视图中代码段、数据段仍然为空,可执行文件相应的数据仍未拷贝到主存中。原来系统会通过可执行文件中头部信息指定的执行程序入口,逐步将相应的段数据拷贝到主存中,并利用缺页中断位置建立相应的页表结构。
这就是我们在执行一个可执行程序时,对于操作系统来说发生了什么。这篇博文可能对于一些基础不太牢固的同学来说有些深奥,但是大家可以根据自己不懂的地方去专项搜索一下。只要坚持看下去,总会理解的。
- 一起来学内存(二)
- 一起来学内存(一)
- 一起来学SQL(二)
- 一起来学Android Studio:(二)Gradle
- 【一起来学C语言】数组(二)
- 【一起来学C语言】函数(二)
- 一起来学springSecurity安全框架(二)
- 一起来学Makefile(一)
- 一起来学android(3)
- 一起来学SQL(一)
- 一起来学SQL(三)
- 一起来学SQL(四)
- 和我一起来学iOS(二)iOS中的一些约定、模式与三种回调机制
- 和我一起来学iOS(二)iOS中的一些约定、模式与三种回调机制
- 【一起来学C语言】数组(一)
- 【一起来学C语言】函数(一)
- 一起来学cdecl
- 一起来学SQL
- 任务堆栈
- java蝴蝶效应
- Celery架构
- in、or、exists区别
- 搭建自己的Spring Initializr服务器
- 一起来学内存(二)
- 每日打卡 2017.03.07 POJ题目分类 水题
- kmp
- 更好的理解git rebase git merge
- ASP.NET MVC5 网站开发实践
- Frogger【最小生成树的变形】---路径上最小的最大权
- leetCode练习(494)
- 全双工
- 框架的使用(一):scrapy