arch
目录
init
目录
init
目录下有main.c源文件,是整个linux内核启动的开始kernel
目录
lib
目录
MenuOS系统由Linux内核镜像和根文件系统集成起来的
上图所示,在实验楼linux环境下,利用图示命令启动MenuOS系统。
qemu
仿真kernelbzImage
是压缩的内核映像文件系统和内核是完全独立的两个部分,linux启动第一个必须挂载根文件系统
使用gdb跟踪调试内核,使用两个参数,-s 和-S
- -s 是在1234端口上创建了一个gdb-server
- -S 是在CPU初始化之前冻结起来
利用target remote:1234
建立连接,在start_kernel
处建立断点,输入c
继续执行,将会看到,系统开始启动执行,到start_kernel
处停止。
再设置一个断点rest_init
继续执行,停在断点处
start_kernal()函数
在位于init目录下的main.c文件中,有内核启动的起点函数start_kernal()
在此函数调用之前,代码主要工作是完成硬件的初始化等。
struct task_struct
类型的变量。是进程描述符,使用宏INIT_TASK直接对其进行初始化。task_struct
就是内核线程,init_task就是0号进程,是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程,最后演变成idel进程rest_init()函数
kernel_thread()
函数作用是创建新的内核线程,除了0号进程,其余所有的内核线程都是由kernel_thread()这个接口产生的。下图所示是kernel_thread()的源代码。
kthreadd()
函数的任务是管理和调度其他内核线程,可以看到在kthreadd()
代码中,有一个while(1)循环执行,将进的内核线程加入到kthread_creat_list全局链表中。也就是当调用kernel_thread()
创建的内核线程会被加入到链表中
针对于rest_init()函数来说,会启动三个进程,分别是idle(0号进程)、kernel_init(1号进程)、kthreadd(2号进程)
idle(0号进程) 由init_task进程创建后,调用cpu_idle()演变而成,
kernel_init(1号进程)由idle进程调用kernel_thread()创建,在内核空间完成初始化后, 演变成init程序,init进程是内核启动的第一个用户态进程。<font color="Tomato">kernel_init运行在内核空间,随后会完成从内核态向用户态的转变,变成init进程,运行在用户空间</font>在系统启动完成完成后,init将变为**守护进程**监视系统其他进程。
kthreadd(2号进程)由idle通过kernel_thread创建,并始终运行在内核空间, 负责所有内核线程的调度和管理,也是大部分创建的内核进程的父进程。
下图所示,是linux内核启动的流程示意图:
参考资料:
内核启动阶段进程分析
Linux下1号进程的前世(kernel_init)今生(init进程)----Linux进程的管理与调度(六)
在分析linux内核启动过程中,设计到了好几个进程的启动与转变,书上的描述方式是 内核线程 但是创建的又是进程,我就分不清楚内核线程和进程的关系,我就去找了些概念:
可以看出,进程和线程是包含的关系,对于书上内核线程的描述就更加迷惑了,又查找了关于linux系统下的进程与线程相关资料:
2018-2019-1 20189206 《Linux内核原理与分析》第四周作业
原文:https://www.cnblogs.com/zz-1226/p/9877480.html