Linux内核分析,gdb调试linux内核--第三周

Linux内核分析-gdb调试linux内核


一:准备

为了更好的追踪分析内核运行,自己搭建平台分析。按下面方法搭建


Linux内核分析,gdb调试linux内核--第三周_第1张图片


其中要注意的是如果如果编译出现ubuntu fatal error : sys/types.h:

没有那个文件或目录 这个错误的时候,是有可能你用的是64位系统,而这里要编译成32为的程序问题,你可以安装install the package libc6-dev-i386就可以解决这个问题了。

然后 启动内核调试
Linux内核分析,gdb调试linux内核--第三周_第2张图片

Linux内核分析,gdb调试linux内核--第三周_第3张图片

这个过程并不复杂,自己按步做做就可以了。下面是重点分析一下分析start_kernel函数的启动过程。
代码在:http://codelab.shiyanlou.com/xref/linux-3.18.6/

二:分析

start_kernel

比较重要的几个函 数在执行start_kernel时,期初会对CPU、内存等各种硬件设备进行初始化,这期间涉及到非常多的不同内核模块的初始化。
set_task_stack_end_magic(&init_task); //init_task 相当于前章所说0号进程的PCB
// ...
trap_init(); // 中断初始化向量,不同的cpu有不同的中断初始化方法
mm_init(); // 内存管理模块的初始化
sched_init(); // 进程调度初始化
// ...
rest_init(); // 启动1号进程


 
   
现在重点分析一下,rest_init
void rest_init(void)
{
    int pid;
    ………………
    kernel_thread(kernel_init, NULL, CLONE_FS);
    numa_default_policy();
    pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);  //内核管理线程
    rcu_read_lock();
    kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
    rcu_read_unlock();
    complete(&kthreadd_done);
 
    init_idle_bootup_task(current);
    schedule_preempt_disabled();
    cpu_startup_entry(CPUHP_ONLINE);   // 调用 cpu  idle 0号进程调用起来 cpu_idle_loop


}


其中kernel_thread,它的功能是用来fork一个内核线程。所以在这里,kernel_init内核线程被创建,进程号为1。当运行到cpu_idle_loop()时init_task的任务基本上已经完全结束了,它将沦落为一个idle task。其实它就是一个while(1) 循环,在循环中它将会调用schedule函数以便在运行队列中有新进程加入时切换到该新进程上。至此start_kernel运行完毕

三,总结

可以看到内核的各个模块的初始化都统一在start_kernel完成,这个和现在很多大型的系统的架构组织方式一样的,内核在这里启动了一个idle进程负责后来各个进程的调度。
在分析的最后想到几个问题,以后继续分析,1:既然有start_kernel对各种模块的初始化,按照组织方式,应该有个stop 或 end kernel 对各种模块进行资源的释放或结束的,暂时还不知道在那里进行。2:我自己写过的一个智能家居管理程序也是有类似的程序结构,有一函数对系统中的各个模块初始化,但是模块在初始化的过程中必须把包含各个模块的环境指针嵌入来给模块间的相互调用,但是这样导致模块间内嵌严重,linux内核在模块间功能互相调用的问题是如何解决的,后续也得慢慢研究。故待续!



你可能感兴趣的:(编程)