最近在研究 Linux Kernel, 由于我看问题喜欢直接看本质, 所以直接从代码开始看起,
但是 Linux 发展到现在代码何其多, 何其复杂, 里面的流程, 逻辑, 甚至各种变量绝对不是
我以前开发的项目能比的, 比如说里面全局变量的大量使用, 各种 goto 的使用,
所以必须要有一个好的阅读方法和好的阅读手段. 阅读代码的 Emacs 和 cscope 足以.
但是对于习惯 gdb 调试的我, 还是希望可以利用 gdb 的强大优势帮助学习. 在加上
QEMU 来作为 kernel 的运行平台, 这样的组合不事半功倍都说不过去.
经我测试 linux-2.6.24 和 linux-2.6.25 没有 KGDB 的支持. 为了能有 KGDB 的
支持, 我选择版本稍微高一点内核.
确保下面的被选中
OK, 下面开始编译内核
这里可以选择多种安装方式, 可以选择从源码安装或者从发行版的二进制安装.
作为一个比较喜欢追根究底的 geek, 我选择的是源码安装.
另外, 我调试的只是 kernel, 所以没有硬件虚拟话我是可以忍受的,
所以我把 kvm 从编译参数那里去掉了.
注意, 因为我不想把 qemu 和我系统的 qemu 冲突, 我简单的将 qemu
安装在 qemu 源码目录下.
静态编译的选择很重要, 如果不选择的话, 需要把 libc.so 和 ld.so 等
复制到文件系统里面, 稍微麻烦一些, 这里我们选择最简单的方式.
另外这个版本静态编译的时候 mount umount会出错, 方正对我来说不需要,
我暂时去掉.
执行 make install 后, 会在 busybox 的源码目录地下创建一个 _install
的文件夹, 这个文件夹就是需要复制到文件系统里面的东西.
# make install
首先创建一个虚拟盘, 并挂载到当前 tmp 目录下.
然后把编译好的 busybox 复制到挂在虚拟盘的目录里面.
创建一些必须的设备文件, 其实设备号几乎是通用的, 所以我直接把本机的设备文件
复制过来了.
在运行的时候碰到了 init 段错误的问题. 我不知道是不是静态编译导致的.
解决这个问题有两个办法, 或者从其他发行版复制一个静态的 busybox过来,
我试过, 没有问题. 或者把内核启动参数改为 init=/bin/sh 不让 kernel
去启动 init. 我选的是后者.
-s 表示用默认的 1234 端口, 开启 gdb server
在我的 Emacs 里面, 使用 /tmp/gdb/bin/gdb –annotate=3 ~/Develop/Linux/linux-2.6.34/vmlinux
来启动, 进去以后, 设置断点, 然后 target remote localhost:1234 连接 gdb server