os内核入门-3 linux0.11编译介绍

张开发
2026/4/14 21:58:54 15 分钟阅读

分享文章

os内核入门-3 linux0.11编译介绍
1. linux0.11编译过程与目标文件系统的学习一个软件做到可以移植参考在某个电路板上运行起来我觉得首要解决的问题就是编译的过程。弄清楚要在电路板上运行的二进制文件是由哪些源代码生成的又是用什么编译工具生成的了解了这些我们就可以造一个在电路板上运行的有OS的软件系统了所有软件代码技术all in control自主可控。很荣幸我们学习的这套linux0.11的源码就是全公开的所以赶快开始研究一下吧。回顾一下我们编译运行的过程cd0-prepEnv/hit-oslab-qiuyu/oslab/linux-0.11make../runmake后出现Image表示编译成功如下tools/build boot/bootsect boot/setuptools/kernelImageImage目标文件我们执行run命令的时候虚拟机就运行起来了OS先看下这个run其实是一个shell脚本vim run可以看到$OSLAB_PATH/bochs/bochs-gdb-q-f$OSLAB_PATH/bochs/bochsrc.bxrcbochs-gdb是一个x86硬件平台的开源模拟器跟我们常用的Vmware和VirtualBox虚拟机一样bochs运行对应的配置文件为bochsrc.bxrcvim bochsrc.bxrcfloppya:1_44$OSLAB_PATH/linux-0.11/Image,statusinserted可以看到这里加载的二进制镜像文件就是Image综上编译产生的Image文件就是我们的目标文件这个文件可以在虚拟机上运行也就是说可以在实际的电路板上运行。下面我们先看一张图了解下这个Image是怎么产生的在编译的时候最后可以看到cp -f tools/system system.tmp strip system.tmp objcopy -O binary -R .note -R .commentsystem.tmp tools/kernel tools/build boot/bootsect boot/setuptools/kernel Image首先把system文件复制了一份到system.tmpstrip删除目标文件中的全部或者特定符号这样可以减小可执行文件的大小。objcopy -O binary把目标文件system.tmp的内容从elf文件格式变成kernel的二进制格式build程序把boot/bootsectboot/setup tools/kernel这三个文件的执行头删除然后把他们顺序组合在一起产生一个名为Image的二进制内核映像文件。上面的打印是通过什么源码产生的答案在编译工具make所使用的MakeFile文件vim MakefileImage: boot/bootsect boot/setuptools/system tools/build cp -f tools/system system.tmp strip system.tmp objcopy -O binary -R .note -R .comment system.tmp tools/kernel tools/buildboot/bootsect boot/setup tools/kernel $(ROOT_DEV) Image这个tools/build是什么vim Makefiletools/build: tools/build.c gcc $(CFLAGS) \ -o tools/build tools/build.c可以看到build程序是由tools/build.c编译来也就是作者自己写的一个c程序后面章节详细介绍。2. 编译过程和make工具上面的分析可以看到目标文件**Image**是由Makefile里面的代码规定怎么生成的下面先介绍下makefile对编译链接有一个基础的认识。什么是make工具和makefile这里用到的make工具也叫GUN make是一个开源命令工具他解释了makefile中的指令。在makefile文件中描述了整个工程所有文件的编译顺序、编译规则。其中包括工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要的可执行文件。 Make工具是告诉了怎么干活具体干活还是要靠编译器。上面说到build程序把boot/bootsect boot/setuptools/kernel这个三个程序文件变成了一个其中boot/bootsect boot/setup本身就是汇编语言就使用**8086的汇编器**进行汇编和链接tools/kernel是c源码使用GUN出品的开源编译器**gcc**进行编译。你一定对这个过程比较好奇吧请往下看程序编译目标程序的过程是什么预处理 ---- 编译 ---- 汇编 ---- 链接1预处理在该阶段编译器将C源代码中的包含的头文件如stdio.h添加进来如果单独执行此步骤我们使用参数”-E”用法gcc -E hello.c -o hello.i作用将hello.c预处理输出hello.i文件。2编译在这个阶段中gcc首先要检查代码的规范性、是否有语法错误等以确定代码的实际要做的工作在检查无误后gcc把c的高级语言代码翻译成低级的汇编语言。如果单独执行此步骤我们使用参数”-S”用法gcc –S hello.i –o hello.s作用将预处理输出文件hello.i汇编成hello.s文件。3汇编把汇编语言书写的代码转换为机器可识别的机器指令二进制。编译后产生的机器指令文件在linux中默认后缀为“.o”虽然可被机器识别但是还不能被执行。如果单独执行此步骤参数“-c”用法gcc –c hello.s –o hello.o作用将汇编输出文件hello.s编译输出hello.o文件。4链接将多个目标文件或者目标文件和库文件链接称为可被操作系统执行的可执行程序。链接器不检查函数所在的源文件只检查所有目标文件的定义的符号。将目标文件使用的函数和其他目标或者库文件中的相关符号进行合并并对所有文件中的符号进行重新安排并连接系统相关文件最终生成可执行程序。如果单独执行此步骤参数“-o”用法gcc hello.o –o hello作用将编译输出文件hello.o链接成最终可执行文件hello。研究程序研究到二进制也算到头了。二进制怎么给cpu运行可以学习下微机原理知识这里不展开说明了。静态库在链接阶段会将汇编生成的目标文件.o与引用到的库linux下.a文件windows下.lib文件一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。动态库动态库在程序编译时并不会被连接到目标代码中而是在程序运行时才被载入。不同的应用程序如果调用相同的库那么在内存里只需要有一份该共享库的实例规避了空间浪费问题。什么是elf可执行文件编译完成后的目标文件一般是一个elf (Executable and Linkable Format)文件比如**tools/****system**就是一个elf可执行文件。再比如gcc hello.c –o hello的目标文件hello或者a.out都是elf文件elf文件是可以运行的。我们打开一个elf文件可以看到ELF字样但是其他部门我们直接是看不到内容的这里有一个工具readelf-a a.out读出目标文件max.o的ELF Header和Section Header Table另外Linux下的反汇编命令objdump -d a.out hello.txt它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。更多ELF知识参考https://blog.csdn.net/daide2012/article/details/73065204objcopy -o binary什么是binary文件这里所谓的“二进制”英文称为raw binary。这种程序只包含**机器码**。而ELF程序还包含有其它额外的信息如段的加载地址运行地址重定位表符号表执行ELF程序则需要一个ELF Loader。Linux内核启动的时候往往是没有ELFLoader的所以只能采用raw binary格式。所以**Image**就是一个binary文件。后记linux知识是有点多随便写点都又超篇幅了但是能学到的东西也多。Makefile文件的具体分析放在下次文章里面然后尽快进入内核源码分析。“那路谈OS与SoC嵌入式软件”欢迎关注个人文章汇总https://thatway1989.github.io

更多文章