Linux内核的启动过程---linux内核学习笔记(三)
内容一:实验报告相关说明。
所学课程:《Linux内核分析》MOOC课程
链接:http://mooc.study.163.com/course/USTC-1000029000
代码来源于孟宁老师的课件
虚拟实验室实验截图
这一小节感觉学的莫名奇妙,似乎并没有学到Linux内核启动的太多知识,因为很多初始化是自己看不懂的。所以自己只能简单的重复一下老师上课讲的东西,并搜素一下相关知识加以拓展,将此次的作业变成了课后小结!
内容二:gdb相关
和所有常用的调试工具一样,gdb提供了以下功能:
1:监视程序中变量的值
2:在程序中设置断点
3:程序的单步执行
在使用gdb前,必须先载入可执行文件,因为要进行调试,文件中就必须包含调试信息。
实验中:(gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表 。file <文件名> 其作用为加载被调试的可执行程序文件
其他部分实用知识请参考 http://blog.csdn.net/liigo/article/details/582231
内容三:Linux内核启动过程浅析
内核几乎所有模块的初始化都会经过start_kernel来进行,分析从init文件中的main.c开始。 start_kernal函数位于main.c的第500行。
start_kernal函数相关注释可以参考:http://www.cnblogs.com/hpunix/articles/2006782.html
其中第510行的函数,其原型如下:
297 void set_task_stack_end_magic(struct task_struct *tsk) 298 { 299 unsigned long *stackend; 300 301 stackend = end_of_stack(tsk); 302 *stackend = STACK_END_MAGIC; /* for overflow detection */ 303 }
其中&init_task的init_task的声明如下:
/* Initial task structure */ struct task_struct init_task = INIT_TASK(init_task);
INIT_TASK(init_task)是一个 #define INIT_TASK(tsk){......} 形式的宏定义。而且注释也说明此处声明的是 Initial task structure。即0号进程的PCB
综合起来也就不难理解老师说的:init_task是手工创建的PCB,0号进程就是idle进程
接下来提到了一下初始化
561 trap_init(); //中断初始化
562 mm_init(); //内存管理模块初始化 .... 569 sched_init(); //调度模块初始化 ....
679 /* Do the rest non-__init'ed, we're now alive */
680 rest_init(); //其他内容初始化
....
其中trap_init中有一个需要重点关注:(具体情况自己还是不明白)
839 set_system_trap_gate(SYSCALL_VECTOR, &system_call);
还有个就是 rest_init(),这个函数主要是创建并启动1号进程init。
393static noinline void __init_refok rest_init(void) 394{ 395 int pid; 396 397 rcu_scheduler_starting(); 398 /* 399 * We need to spawn init first so that it obtains pid 1, however 400 * the init task will end up wanting to create kthreads, which, if 401 * we schedule it before we create kthreadd, will OOPS. 402 */
//创建1号线程,kernel_init函数将完成设备驱动程序的初始化,并调用init_post函数启动用户空间的init进程。 403 kernel_thread(kernel_init, NULL, CLONE_FS); 404 numa_default_policy();
//创建kthreadd内核线程,它的作用是管理和调度其它内核线程。
405 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
406 rcu_read_lock();
407 kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
408 rcu_read_unlock();
409 complete(&kthreadd_done);
410
411 /*
412 * The boot idle thread must execute schedule()
413 * at least once to get things moving:
414 */
415 init_idle_bootup_task(current);
416 schedule_preempt_disabled();
417 /* Call into cpu_idle with preempt disabled */
//其内执行cpu_idle_loop, cpu_idle_loop是一个while(1)循环,当系统没有任何需要执行的进程的时候就调度到idle进程
418 cpu_startup_entry(CPUHP_ONLINE);
419}
内容四:小结
1::linux内核的内知识点太多了。仅其中的start_kernel自己学的就云里雾里。所以学习任重而道远!必须踏踏实实跟着老师学习。
2:跟着老师学习了重要的调试工具:gdb,自己用的开发软件MDK也有类似的debug功能,只不过是图形界面下,而gdb是在命令行模式下进行的,而且似乎后者功能更多且使用的更广泛。
3:start_kernel内做的几件重要的事情还是大致明白了,并了解了0号进程和1号进程的来源和相关作用。
4:程管理和调度其它内核线程的线程是kthreadd内核线程。也是在rest_init()中创建的。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步