Linux启动为什么没有先执行main函数
Linux启动为什么没有先执行main函数
学过C语言的都知道,用C语言设计的程序都有一个main函数,而且是从main函数开始执行的。Linux 0.11的代码是用C语言编写的,奇怪的是,为什么在操作系统启动是执行的是三个由汇编写成的程序,然后才开始执行main函数?为什么不像我们熟知的C程序那样,从main函数开始执行呢?
通常,我们用C语言编写的程序都是用户应用程序,这类程序的执行有一个重要的特征,就是必须在操作系统的平台上执行,这也就是说要有操作系统为应用程序创建进程,并把应用程序的可执行代码从硬盘加载到内存。现在我们讨论的是操作系统,不是普通的应用程序,这样就出现了一个问题,应用程序是由操作系统加载的,操作系统该由谁加载呢?(说白了这个过程就是要为linux系统的C程序的执行搭建一个平台)
加载操作系统的时候,计算机刚刚加电,只有BIOS程序在这行(BIOS在内存中加载中断向量和中断服务程序),而且此时计算机处于16为实模式的状态,通过BIOS提供的16位中断向量表和16位的中断服务程序,将操作系统分部分(具体说是分三批)的加载到内存当中(因为CPU设计为只能运行内存当中的东西,这里为保护模式做准备),加载完内核程序之后则要废除原有的中断向量建立一套操作系统自己的中断向量表和中断服务程序。操作系统写在CD 、软盘、硬盘上(早期的LINUX写在软盘上),但无论写在什么存储器上,BIOS总是能找到系统所在的位置,因为是“两头约定”和“定位识别”规定的存在。
在加载完成后,仍然没有立即执行main函数,而是打开A20(这意味着CPU可以进行32位寻址,寻址空间为4GB,2的32次幂),打开pe和pg,建立IDT、GDT...然才开始执行main函数。
Linux 0.11是一个32位的实时多任务的现代操作系统,main函数肯定要执行的是32位代码,编译操作系统代码时,是16位和32位两个不同的编译选项的,如果选了16位的,C编译出来的就是16位模式的,结果可能是int型变量的只有两个字节,而不是32位的四个字节,而linux要的是32位的编译结果,只有这样才能成为32为的操作系统代码,这样的代码才能用到32位总线(即打开A20后的总线),才能用到保护模式和分页,才能成为32位的实时多任务的现代操作系统。
开机时的16位实模式与main函数执行需要的32位保护模式之间有很大的差距,这个差距由head.s来弥补,这期间,head程序打开A20,打开pe和pg,废旧的、16位的中断响应机制,建立新的32位的IDT...这些工作做完了,计算机已经处于32位保护模式状态了,调用32为main函数的一切条件已经准备完毕,这时可调用main函数,后面的操作就可以用32为编译的main函数完成。