还有5天就过年了,沟通了这么久,TI的印度佬终于把示例写好,发给我当新年贺礼,同时也把我这一个月来看那么多文档,研究了那么多问题的努力全部击碎了——搞了半天,就因为你们丫的文档不写清楚,让我因为字节序列问题折腾了一个月!还不是大小端问题,仅仅只是2字节2字节的反转!虽然我极其希望这只是一个内部入出栈的一个缓冲问题,但我也同意同事的说法,这可能只是硬件一个bug!
好吧,是不是bug也不关事了,进入主题:编译Linux内核
据Joel所称,美国的优秀程序员在孩童时代已经通过编译Linux内核,建立编程世界的好奇心。学习始于模仿,linux及其衍生的一系列开源软件,正好是我们学习模仿的对象,无论从某种聪明的设计也好,某种聪明的机制也好,等等等等。
编译Linux内核首先要有一份内核源代码,从www.kernel.org选择你所喜欢的源代码。如果你缺乏探索精神,那么版本2.6可能是你最好的选择,因为这个内核版本网上的资料比较齐全。按照以往规则,版本号x.y.z中的y是偶数则代表稳定版本,奇数则代表开发版本,但目录好像3.7.x是最新的稳定版本,我不晓得这个规则是不是改变了,不过这不重要。
其次你需要一个linux环境,ubuntu桌面是一个好的选择,终端运行
sudo apt-get install •build-essential
安装编译环境
如果你在x86机器上运行内核,那编译内核是相当简单的。你只需在终端内CD到内核目录,然后:
make defconfig
make bzImage
(或make bzImage–jN, N可以是任何数字,代表编译线程数,一般取决CPU的能力)
*直接make是可行的,但不会生成bzImage
这样在当前目录会生成一个未压缩的内核映像vmlinux,而在arch/x86/boot目录下会生成压缩内核映像bzImage
make defconfig这一步其实把arch/x86/configs下的i386_defconfig复制一份放在当前目录,并重命名为.config。你不能看到它,因为以.开头的文件就隐藏的,ctrl+h可以显示它。当你make bzImage,将根据这个文件,编译所指定的内核模块和驱动,编译机制取决于makefile,kbuild, xconfig的相互依赖,如果有兴趣为自己的开源软件(例如busybox)提供这样一套机制,可以深入研究这些文件,阅读源代码,makefile可能也是一个好的开始。arch下目录对应各种CPU架构,在各种CPU架构目录中的configs都有一些定义好的config文件,将其拷贝到源代码当前目录,并命名为.config,然后make,都可以生成配置好的内核映像,当然,你可能还需要对应的交叉编译工具。
那么如何运行linux内核?你可以直接使用qemu虚拟机。终端运行安装qemu:
sudo apt-get install qemu-kvm
然后运行
qemu –kernel bzImage
即可
这时,打印一连串信息之后,你会发现,自己并未进入桌面或shell,因为我们没有启动脚本去做这个事。没有文件系统,没有initramfs,也没有shell程序,这些内容,我会另外开篇去讲明白,好奇可先查阅http://blog.linux.org.tw/~jserv/上的《深入理解 Linux 2.6 的 initramfs 機制》。实际上,你完全可以引用ubuntu的initrd.img,虽然启动脚本会产生很多错误,例如文件系统无法挂载,但最终,你可以进入busybox命令行,执行一些基本的操作。运行:
qemu –kernel bzImage –initrd/boot/initrd.img
你也可以修改ubuntu的grub启动在真实机器上,或者vmware做这个事情。这个请查阅相关资料,不赘述。——这算课后练习?哈哈
实际,利用linux内核源代码,做移植做嵌入式开发,我们都需要深度定制内核,决定编译哪些内核模块进行内核映像,开启哪些内核模块,哪些内核模块在需要被加载等等。
make menuconfig可以帮我们生成一个自定义的.config文件。这上面一些基本的东西,例如,调试机制,硬件驱动,SMP。make menuconfig可能会因为分辨率问题报错。放大你的终端窗口即可。makexconfig, make gconfig提供一样的功能但具备图形界面,前者需要安装qt库,后者需要GTK+库。
qemu -S -s –kernel bzImage可以让内核一启动就挂起,等待gdb连接调试:
gdb vmlinux
target remote localhost:1234
这样就可以单步跟踪内核启动了。