文章插图
【Linux系统启动时为什么没有最先调用main函数?】
学过C语言的人都知道,用C语言设计的程序都有一个main函数,而且是从main函数开始执行的 。linux0.11的代码是用C语言编写的 。奇怪的是,为什么在操作系统启动时先执行的是三个由汇编语言写成的程序,然后才开始执行main函数;为什么不是像我们熟知的C语言程序那样,从main函数开始执行呢?
通常,我们用C语言编写的程序都是用户应用程序 。这类程序的执行有一个很重要的特征,就是必须在操作系统的平台上执行,也就是说,要由操作系统为应用程序创建进程,并把应用程序的可执行代码从硬盘加载到内存 。现在我们讨论的是操作系统,不是普通的应用程序,这样就出现了一个问题:应用程序是由操作系统加载的,操作系统该由谁加载呢?
从前面的只是中我们知道,加载操作系统的时候,计算机刚刚加电,只有BIOS程序在运行,而且此时的计算机处在16位实模式状态,通过BIOS程序自身的代码形成的16位的中断向量表及相关的16位的中断服务程序,将操作系统在软盘上的第一扇区(512字节)的代码加载到内存,BIOS能主动操作的内容也就到此为止了 。准确的说,这是一个约定 。对于第一扇区代码的加载,不论是什么操作系统都是一样的;从第二扇区开始,就要由第一扇区中的代码来完成后续的代码加载工作 。
当加载工作完成后,好像仍然没有立即执行main函数,而是打开A20,打开pe、pg,建立IDT、GDT......然后才开始执行main函数,这是什么道理?
原因是,Linux0.11是一个32位的实时多任务的现代操作系统,main函数肯定要执行的事32位的代码 。编译操作系统代码时,是由16位和32位不同的编译选项的 。如果选择了16位,C语言编译出来的代码是16位模式的,结果可能是一个int型变量,只有2字节,而不是32位的4字节......这不是Linux0.11想要的 。Linux0.11要的是32位的编译结果 。只有这样才能成为32位的操作系统代码 。这样的代码才能用到32位总线(打开A20后的总线),才能用到保护模式和分页,才能成为32位的实时多任务的现代操作系统 。
开机时的16位实模式与main函数执行需要的32位保护模式之间有很大的差距,这个差距谁来填补?head.s做的就是这项工作 。这期间,head程序打开A20,打开pe、pg 。废弃旧的、16位的中断响应机制,建立新的32位的IDT......这些工作都做完了,计算机已经处在32位的保护模式状态了,调用32位main函数的一切条件已经准备完毕,这时顺理成章地调用main函数 。后面的操作系统就可以用32位编译的main函数完成 。
推荐阅读
- 华为升级鸿蒙系统后,只需打开两个开关,垃圾文件会自动识别清理
- 苹果发布各大硬件设备系统升级,主要修复问题
- 抖音 Android 性能优化系列:启动优化之理论和工具篇
- 不管什么手机,管理好后台自启动运行,再用3年也很流畅
- 软件架构-解密电商系统商品营销-会员模块业务!解读模块工具
- Linux常用命令:chmod修改文件权限 777和755分别是什么意思?
- 从零开始教你每月网上申报 网上纳税申报系统登录
- 千年叶 茶脉绵长 西安市新城区博物馆进社区系列文化活动启动
- 铁观音茶文化系统成为乡村振兴动力源泉
- iOS系统可以降级,仅限小部分用户