《Linux内核原理与分析》第四次作业

时间:2022-05-20 05:46:18

跟踪分析Linux内核的启动过程

使用实验楼的虚拟机打开shell

《Linux内核原理与分析》第四次作业

《Linux内核原理与分析》第四次作业

使用 gdb 跟踪调试内核

使用 qemu

qemu  -kernel  linux-3.18.6  /arch/x86/boot/baImage  -initrd  rootfs.img

参数:

  — s:在初始化时冻结CPU

  — S:为gdb分配1234端口

《Linux内核原理与分析》第四次作业

gdb调试

另开一个shell窗口

        — gdb
—(gdb) file linux-3.18.6/vmlinux #在gdb界面中target remote之前加载符号表
—(gdb)target remote :1234 #建立连接
—(gdb)break start_kernel #设置断点

《Linux内核原理与分析》第四次作业

《Linux内核原理与分析》第四次作业

从 start_kernel 开始到 init 进程启动

-set_task_stack_end_magic()

     为了检测栈溢出

-smp_setup_processor_id()

    设置对称多处理器

-cgroup_init_early ()

 初始化 Control Groups

-page_address_init()

    页地址初始化(属于内存管理部分)

-setup_arch()

-build_all_zonelists()

-page_alloc_init ()

-setup_log_buf ()

    初始化log 缓冲区(kernel/printk/printk.c)

-pidhash_init ()

    初始化 pid 哈希表

-vfs_caches_init_early ()

-sort_main_extable ()

###初始化中断向量


    -mm_init ()

    内存管理初始化

   -sched_init ()

    调度服务初始化

   -rest_init()

    剩余初始化

             -  kernel_init:init进程

             -  kthreadd:内核线程

             -  cpu_idle进程:代码中一直循环,如果系统中没有可执行的进程时,执行 idle 进程

个人对linux启动过程的理解

   start_kernel()函数的作用是完成linux内核的初始化,几乎所有模块都是由这个函数初始化的,通过阅读代码和使用gdb 工具,完成了下列动作:

   调用sched_init()函数来初始化调度程序;调用page_alloc_init()初始化伙伴系统分配程序;调用trap_init()和init_IRQ()完成异常和中断初始化;调用softirq_init()函数初始化软中断;调用time_init()函数初始化系统和时间;等等。。。

  启动过程分析:计算机上电后,加载BIOS的硬件信息与进行自我测试,读取并执行第一个启动设备内主引导记录内的Bootloader,依据bootloader的设置加载Kernel ,Kernel会开始检测硬件与加载驱动程序。这其中的每一部分都需要大篇的文字描述,这里只是重点从进程角度来了解一下:init_task进程(0号进程)是静态创造的,是内核开发人员创造的,而不是其他进程通过do_fork形成的。它从start_kernel()初始化直到start_kernel()中最后一个函数rest_init(),从rest_init开始,Linux开始产生进程,在rest_init函数中,内核将通过kernel_thread()产生第一个真正的进程(pid=1),而此时init_task的任务基本上已经完全结束了,它将沦落为一个idle 进程,事实上在更早前的sched_init()函数中,通过init_idle(current, smp_processor_id())函数的调用就已经把init_task初始化成了一个idle 进程。