程序是怎样一步步运转起来的
大家好,我是小风哥,当天聊聊程序是怎样一步步运转起来的。
第一步咱们须要知道究竟什么是可口头程序,所谓可口头程序就是一个保留一系列机器指令的文件:
chrome.exe就是上千万上亿条指令组成的一个普通文件,和你写的txt文件没有任何实质的区别,只不过txt文件中的内容是给人看的,而可口头程序中的内容是给CPU口头的。
如今有了可口头程序,接着咱们来运转它,运转一个程序很便捷,双击图标或许在命令行中运转命令:
咱们曾经知道可口头程序其实就是一个文件,文件是保留在磁盘上的。
当咱们双击或许在命令行中运转命令后,第一件事就要找到可口头文件保留在了磁盘的哪个
谁来成功这件事?答案就是操作系统。
实践上操作系统也是一个程序,操作系统是治理咱们写的程序的程序。
操作系统在文件系统的协助下找到可口头程序,接上去操作系统开局解析可口头程序,实践上可口头程序中并不仅蕴含机器指令,这里还有很多其它消息,在Linux下可口头程序普通遵照ELF文件格局:
依据可口头程序的格局操作系统就能找到机器指令或程序运转依赖的全局变量等消息保留在了文件的哪个位置。
既然操作系统曾经识别出了可口头程序,接上去就是关键的一步:加载,load。
所谓加载就是把磁盘上可口头程序中的指令和程序依赖的全局变量等数据copy到内存中:
既然是copy到内存,那么显然操作系统须要为接上去要运转的程序调配内存。
操作系统在内存中找到一段大小适合的闲暇内存调配给接上去要运转的程序:
而后在该内存中划分出几个区域,这几个区域就是咱们相熟的代码区、数据区、堆区和栈区:
其中代码区和数据区中的内容来自可口头程序的代码段和数据段:
而堆区和栈区则是程序在运转环节中经常使用的,这两个区域中的内容不依赖可口头程序自身。
值得留意的是,所谓的堆区和栈区只是一个形象的概念,真正的物理内存中并没有一块所谓的堆区或许栈区。
任何一段内存都可以被用作堆区或许栈区,这就像停车场有vip区或许普通区,所谓vip区只不过一种商定,普通区和vip区的停车位没有任何实质的不同,作为停车场治理员只需你快乐实践上可以把任何一块普通区划分为vip区。
当然,程序的内存区域中除了看到的这些区域或许还有其它区域,这取决于程序能否依赖灵活库。
假设该程序依赖灵活库,那么在程序运转时还须要把依赖的灵活库也加载出去,加载到哪里呢?
不要忘了堆区和栈区的增长方向是相反的,因此这两边的闲暇区域正好可以应用起来寄存灵活库:
这一步成功之后程序就算加载终了接上去可以运转了,但程序是怎样运转的呢?CPU怎样能知道该从哪里开局运转这个程序呢?
答案还得在可口头程序中寻觅。
编译器在编译生成可口头程序时会记载下这个程序第一条指令的所在位置,以elf可口头程序为例,经常使用readelf工具你可以检查elf可口头程序的内容:
留意看Entry point address这一项,这就是该程序的第一条机器指令所在地址。
当操作系统选择把CPU调配给刚创立的程序时会用这个值去初始化CPU的指令寄存器,这样CPU就知道该从哪里开局运转该程序了。
这就是你双击一个图标面前的故事。