linux学习2,五分钟学会调试内核,让操作系统打印自己的名字
发表于: 2018-12-08 15:37:50 | 已被阅读: 110 | 分类于: Linux笔记
上一节粗略的介绍了如何下载和编译 linux 内核,可只是编译出内核没什么意思,能不能让它跑起来呢?当然可以,本节的内容就是
qemu 模拟器
打算让“linux内核跑起来”,在什么地方跑呢?如果手边有闲置的电脑,那当然好。可是我只有一台电脑,也不想花钱买开发板,有没有办法让“linux内核跑起来”呢?当然有办法了,使用模拟器就好了。本节打算介绍的是 qemu 模拟器,它是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和 qemu 模拟出来的硬件打交道,qemu 将这些指令转译给真正的硬件。正因为 qemu 是纯软件实现的,所有的指令都要经 qemu 过一手,性能会比较低,不过这个无所谓了,我们只是想用它来调试内核,并不是用来做复杂工作的。
在 ubuntu 上安装 qemu 是方便的,只需执行下面这条命令就可以了。
sudo apt-get install qemu
输入完上面的命令,按 tab 键,可以看到以下结果:

sudo apt-get install qemu-system-x86
回车,待安装结束,输入以下命令
qemu-system-x86_64 --version

编译 linux 内核
上一节已经介绍如何下载和编译内核了,这里又编译一次是因为我们打算调试内核,因此有些配置项要勾选。而且,在这次编译过程中,我遇到了几个错误,这里再介绍下如果遇到错误,如何解决它。
头条不能留外链,如果有朋友不方便下载内核,可以在评论区留言,我可以把要用到的东西都发过去。
我们新建一个 kernel 目录,把下载好的内核 linux-2.6.26.tar.gz 放进去,然后依次执行以下命令
tar xf linux-2.6.26.tar.gz
cd linux-2.6.26
make x86_64_defconfig
make menuconfig
这几条命令依次是:解压内核源码,进入解压后的命令,按照 x86_64 的架构(因为我的 ubuntu 主机是 x86_64 位的,编写x86_64程序比较方便)默认配置内核,最后一条命令执行后,就会进入到图形配置界面,进入 Kernel hacking,选中下图中的配置,按空格勾选之:


make bzImage -j4
这几条命令上一节介绍的比较详细,不清楚的朋友可以再翻回去看看。
在我的 ubuntu 上,编译到这里就报错了:

vim arch/x86/vdso/Makefile

可是,编译过程中,又报这个错误了:

vim arch/x86/lib/copy_user_64.S


grep -r __mutex_lock_slowpath

vim kernel/mutex.c
发现明明定义了这个函数,怎么还会提示没定义呢?猜测可能是 CONFIG_DEBUG_LOCK_ALLOC 宏定义搞的鬼:

vim .config

CONFIG_DEBUG_LOCK_ALLOC=y
保存修改,继续编译终于不再报错了,稍后片刻,发现终于成功了:

使用 qemu 模拟运行编译出的 linux 内核
方法是简单的,只需执行以下命令即可
qemu-system-x86_64 \
-m 512M \ # 模拟内存 512M
-smp 1 \ # 模拟器有 1 个核的 cpu
-kernel arch/x86_64/boot/bzImage\ #内核位置
- curses # 使用 curse 图形库

内核虽然很恐慌,但是我们
事实上,一般 C 语言程序都有一个入口函数(这个入口函数通常是 main 函数),linux 内核也有入口函数——start_kernel 函数,在内核源码树的 init/main.c 里。我们打开之,找到 start_kernel 函数,发现它其实就是初始化一些函数而已。我们在最后的几个函数前添加打印信息就好了,请看:

这里要注意的是,内核不能使用 printf 函数,不过内核提供的 printk 函数和 printf 函数的功能很相似。
保存修改后,我们再次编译内核,得到新的 bzImage 后,再使用 qemu 模拟运行 linux 内核:

到这里,其实我们就已经会修改 linux 内核源码了,修改操作系统源码也没有那么复杂,对不?至于如何让 linux 内核不再恐慌,就需要给它提供个文件系统了,怎样提供跟?限于篇幅,我们下一节再介绍。