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()中创建的。

 

 

 

原文地址:https://www.cnblogs.com/esxingzhe/p/4357820.html