科普:程序是怎么执行的
作者:网络转载 发布时间:[ 2015/6/15 10:27:45 ] 推荐标签:程序

Docker是一个建立在操作系统+编译器基础之上的系统,所以了解操作系统,编译器以及程序运行机制对我们理解Docker来说非常重要。本文是一个自己的体会,有很多不精确的地方,目的是希望大家多关注低层,多修炼内功,多读好书。
一直想写篇文章来说明在程序运行过程中操作系统都干了些什么事。下面我试着说明:
首先,任何程序都是有格式的,所谓无规矩不成方圆,任何美的,精巧的事物都是精密组织的,程序也一样。我之前用的多的是c#与java,有趣的是,当时很多人嘲笑java与c#们一直在用脚本写程序,大概在他们眼里c与c++才是真正的程序。但是,现实是现实,其实我们都是在一个叫做虚拟机的程序下写托管代码,它掌握着程序的编译,链接,加载,映射与终执行与终止。它是操作系统,准确的讲是操作系统+编译器。他们是真正的元虚拟机。
然后我来解释下如何运行一个程序:
程序是精巧与复杂的,熟悉它以后你也会觉得它是脆弱的,因为只要有一个bit发生错误,整个系统会崩溃。这个系统是执行文件格式,在linux下叫elf(executable linkable format)而windows下叫pe(portable execute)。我想写操作系统第一步是制定这个规则,不然一切都没有规律。所以我想linux牛,但是ken tomason有过之而无不及,毕竟你是在人家基础之上发展而来的,计算机世界是如此没办法,谁让你在人家下面呢?
我以linux系统为例,简单讲讲程序由编译链接装载与执行。elf文件格式分为很多段—section,总体分为只读可执行的代码段与可读可写的数据段。.txt是典型的代码段,.data.rodata.symbl.rel.got.plt都是数据段。那么,编译器负责将程序员写的程序,编译成elf文件,代码,注视,代码行对应机器码信息,是调试信息啦会进去.txt.code.comment.debug段,常量与静态变量进入.data.rodata.bss。接下来,编译器将引用的头文件中的代码(特指静态编译)与引用的glibc中的库函数打包(链接)到整个可执行文件中,然后在elf文件中设置文件头信息,如段表位置,程序入口位置等信息。当然,这里不得不提的是符号表,与重定位表,他们是整个程序终能跑起来的关键。gcc是靠符号,或者说程序是靠符号来链接的,不管是函数还是变量,都是符号而已,所以从侧面讲,写程序跟写文章没啥区别。程序像个图书馆,每个函数与变量都是书,链接程序好比在图书馆看书,当你看到一个点时,会叫你去某某位置拿另一本书,翻到特定位置开始继续读,如果没找到会爆出链接错误。而重定位表是一次性讲所有对需要跳转的位置进行更改,以确保程序中不存在没有拿到手的书。

sales@spasvo.com