全心思齐网

文件头是什么?

首先,解释一下为什么可执行文件需要有文件头。



对于一个可执行文件来说,操作系统在执行它之前需要知道:

1、它所依赖的操作系统版本,比如有些只能在DOS下运行,有些可以在Windows里运行;有些必须在64位环境下运行等等。

2、它的入口在哪,并不是所有可执行文件的入口都在文件的最前面,还可以在中间,或者最后面,所以需要有东西来描述。

3、它的哪部分是代码,哪部分是数据,因为通常对于代码而言,代码部分应该是只读的,数据部分才是可读写的。

4、哪些数据需要初始化为0,通常,在可执行文件中,有一个叫BSS段的部分,这部分数据需要操作系统在加载可执行文件时对BSS清零。

5、它运行时的虚拟地址是什么,如果无法加载到指定的地址上,操作系统该怎么做(重定向表)。

6、初始的寄存器的值是多少。

……

所以,要描述这些信息,就必须给可执行文件加上一个文件头。否则操作系统就不能正确加载并运行可执行文件。

那么有没有不需要文件头的可执行文件呢?回答是有的。

我能记得的有两种:

第一种是DOS时代的COM文件,这种文件的入口就是它的第一个字节,寄存器的大部分初始化都由自己完成,尺寸不允许超过一个16位的段大小(64KB),功能非常有限。

另一种就是嵌入式开发里用的BIN文件,它的入口就是它的第一个字节,有些BIN文件能自己初始化段寄存器,所以可以基本认为它是一个没有文件头的可执行代码。但是由于BIN没有统一的规范,所以具体到某个BIN文件,就不好说它到底有没有文件头了。

然后,再解释一下为什么不同系统的文件头不一样。

一方面由于历史原因,不同的操作系统都是各个玩各自的,所以造成了格式的差异。但更本质的原因是操作系统环境不同。比如,WindowsXP32位系统中,虚拟地址空间里,用户地址占用的是0x00000000-0x7FFFFFFF的地址范围,内核空间地址是0x80000000-0xFFFFFFFF的地址范围,用户空间是2GB,内核空间是2GB,通常默认是这样的。但是在Linux里,用户空间是3GB,内核空间是1GB,这种内存分布的差异就造成了很多东西都是不同的,包括可执行文件的入口地址范围、可用内存等等,因此Linux里的ELF文件和Windows里的PE文件就不可能定义的完全一样。并且PE格式都包含一个DOS文件头,Linux里是没有这个东西的,PE里还要指定使用Windows子系统的类型,Linux肯定不会支持。而且DLL库和SO库也不一样。所以,因为以上的原因,不同操作系统里的可执行文件头格式也不一样。

匿名回答于2019-06-07 14:31:08


相关知识问答