zoukankan      html  css  js  c++  java
  • Linux系统启动过程的部分理解

     

    作者:xujianguo

     原创作品转载请注明出处,《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

    ——————————————————————————————————————————————————————-————

    实验目的:

           通过gdb调试来加强理解Linux系统启动过程。

    实验环境:

      

            实验楼:www.shiyanlou.com

    实验步骤:

    1.预配置:

    • make menuconfig  
    • kernel hacking—>  
    • compile-time checks and compile options  
    • [*] compile the kernel with debug info

    2.打开实验楼虚拟机,运行3.18.6系统进行初步调试。

    3.启动过程预配置:

    1. qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明:
    2. # -S freeze CPU at startup (use ’c’ to start execution)
    3. # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

     4.另外开启一个终端,进入gdb调试器。

    5.调试启动过程:

    • (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
    • (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
    • (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后

     6.设置相关断点,利用编译命令c和显示命令list来获取启动详情。

     start_kernel:

     cpu_start_entry:

     run_init_process:

     7.启动完成。

    实验分析:

      参考源码:

    http://codelab.shiyanlou.com/xref/linux-3.18.6/init/main.c

       

          系统启动进程是从start_kernel函数中开始执行的,详细代码如下:

     

           从上面的代码可以看出,start_kernel函数开始就完成一部分初始化操作(如中断,trap_init,内存管理mm_init等),配置init_task进程的结构的详细信息;随后进行调度的初始化(sched_init)、时钟设置(time_init)、控制台的初始化启动(console_init())、proc_root_init的运行;然后进行bug检测等辅助环节,最后调用rest_init函数。rest_init函数在启动完init进程后并没有退出,而是继续往下执行道了cpu_startup_entry函数。执行流生成init进程,作为idle进程继续运行下去。

               idle进程:Linux引导中创建的第一个进程(只在内核中存在),完成加载系统后,演变为进程调度、交换及存储管理进程,又称0号进程。

               init 进程:由idle进程创建,完成系统的初始化. 是系统中所有其它用户进程的祖先进程。

    总结:

        通过本次实验,对linux内核启动过程有了些详细了解。pid号为0的原始进程设置了执行环境,然后原是进程开始执行start_kernel()完成Linux内核的初始化工作。包括初始化页表,初始化中断向量表,初始化系统时间等。继而调用 fork(),创建第一个用户进程:kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);idle 进程优先级为MAX_PRIO,即最低优先级。早先版本中,idle是参与调度的,所以将其优先级设为最低,当没有其他进程可以运行时,才会调度执行 idle。而目前的版本中idle并不在运行队列中参与调度,而是在运行队列结构中含idle指针,指向idle进程,在调度器发现运行队列为空的时候运行,调入运行。主处理器上的idle由原始进程(pid=0)演变而来。从处理器上的idle由init进程fork得到,但是它们的pid都为0。init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以,init始终是第一个进程(其进程编号始终为1)。

        谢谢前辈的努力和奉献:)

      



    参考资料:

    http://www.douban.com/note/56531301/

    http://blog.chinaunix.net/uid-23769728-id-3127671.html
      

  • 相关阅读:
    天大复试机试练习_003
    C++随手记--字符串转数字
    C++标准库STL 之 我觉得应该有的方法——split
    apt-get 详解&&配置阿里源
    Nginx 图文详解
    MySQL数据库管理常用命令小结
    oracle数据库备份
    SqlServer数据库备份还原步骤
    mysql数据备份与恢复
    Tomcat架构
  • 原文地址:https://www.cnblogs.com/emochuanshuo/p/4354444.html
Copyright © 2011-2022 走看看