跟踪分析 Linux 内核的启动过程-树莓派实现

跟踪Linux内核启动

之前写了个博客安装openEuler系统的树莓派使用qemu模拟一个内核的运行,里面讲了配置,不同的是我接下来的调试用的都是linux-5.0.1版本内核。
gdb调试内核时必须加两个参数,第一个参数是 -s,这个-s是在1234端口上创建一个gdb-server当打开另一个窗口时,用gdb把带有符号表的内核镜像加载进来,连接gdb server,设置断点跟踪内核。 第二个参数是-S是Cpu初试化前冻结起来。
开一个终端

cd menu
make rootfs

效果如下:
在这里插入图片描述
再打开另一个终端,使用gdb调试

cd linux-5.0.1
gdb
file vmlinux
target remote:1234

打两个断点

b start_kernel
b rest_init

按下c继续执行。按下n一行一行的执行
在这里插入图片描述可以看到一堆初始化。
在这里插入图片描述
通过以上调试可以知道start_init和rest_init函数都在main.c里面。这个main.c在内核文件里的init文件夹下。

代码分析

start_kernel()函数

这个函数被调用前,内核的代码是用汇编写,初始化硬件系统,为C代码的运行设置环境。里面涉及到了内核的主要模块

init_task()函数

	set_task_stack_end_magic(&init_task);

这个init_task就是0号进程,是task_struct类型,也是进程描述符,初始化是通过宏定义INIT_TASK

rest_init()函数

在main.c中的393行
在这里插入图片描述

kernel_thread(kernel_init, NULL, CLONE_FS);
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

这里新建了两个内核线程,一个是kernel_init,一个是kthreadd。
需要注意的是:

对于kernel_thread()是fork一个新进程来执行kernel_init()函数
init_task是用宏进行初始化

kernel_thread执行了kthreadd,创建PID为2的线程,kthreadd是管理和调度其他内核线程kernel_thread。在这个kthreadd函数中有一个for循环,运行了kthread_create_list全局链表中维护的kthread,create_kthread函数是调用kernel_thread生成一个新的进程并加入链表,换句话说其实所有内核进程都是直接或者间接以kthreadd为父进程。
所以其实启动内核创建进程主要逻辑如下:
在这里插入图片描述
综上也就是start_kernel函数进行了大量初始化工作,主要是对硬件的初始化,而rest_init函数是对进程空间的初始化,然后内核启动。

总结与反思

之前从来没对内核进行分析过,所以对我而言算是全新的知识点,看C语言代码还是觉得有点难度,与我之前学过的C语言有所不同,主要分析了两个函数第一个是start_kenerl,第二个是rest_init()。使用init_task()创建了一个0号进程,进行了初始化,在进入rest_init()创建kernel_init()和kthreadd(),第一个是用户进程,第二个是内核线程。
接下来会多读内核源码,多对源码进行分析,多使用gdb调试,多设断点,深刻理解代码运行过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值