zoukankan      html  css  js  c++  java
  • Linux内核学习第三周 Linux启动过程分析

    一.知识点回顾

    1.计算机的“三个法宝”:存储程序计算机,中断,函数调用堆栈;

    2.操作系统的“两把宝剑”:中断上下文的切换(保存现场和恢复现场),进程上下文的切换。

    二.实验内容

    1.启动menuos

    执行命令   cd LinuxKernel/
               qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

    menuos启动成功。

    2.利用gdb跟踪调试内核

    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选项

    另打开一个shell窗口

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

    设置断点rest_init()

    三.总结

    1.start_kernel函数

    start_kernel函数完成linux内核的初始化。几乎每个内核部件都是由这个函数进行初始化的。

    调用sched_init函数初始化调度程序;

    电泳trap_init函数和init_IRQ函数来完成IDT初始化;

    调用time_init()函数来初始化系统日期和时间;

    调用kernel_thread()函数为进程1创建内核线程,这个内核线程又会创建其他的内核线程并执行。

    2init_task进程和idle进程

    init_task进程在Linux中属于一个比较特殊的进程,它是内核开发者人为制造出来的,而不是其他进程通过do_fork来完成。Linux在无进程概念的情况下将一直从初始化部分的代码执行到start_kernel,然后再到其最后一个函数调用rest_init。从rest_init开始,Linux开始产生进程,因为init_task是静态制造出来的,pid=0,它试图将从最早的汇编代码一直到start_kernel的执行都纳入到init_task进程上下文中。在rest_init函数中,内核将通过下面的代码产生第一个真正的进程(pid=1):

    1. static noinline void __init_refok rest_init(void)
    2. {
    3.     ...
    4.     kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
    5.     ...
    6.     cpu_idle();
    7. }

    kernel_init函数最有意思的地方在于它会通过调用kernel_execve来执行根文件系统下的/sbin/init文件(所以此前系统根文件系统必须已经就绪),kernel_execve对用户空间程序/sbin/init的调用发起自int $0x80,这是个从内核空间发起的系统调用,与call_usermodehelper函数本质上是完全一样的。

    而此时init_task的任务基本上已经完全结束了,它将沦落为一个idle task,事实上在更早前的sched_init()函数中,通过init_idle(current, smp_processor_id())函数的调用就已经把init_task初始化成了一个idle task,init_idle函数的第一个参数current就是&init_task,在init_idle中将会把init_task加入到cpu的运行队列中,这样当运行队列中没有别的就绪进程时,init_task(也就是idle task)将会被调用,它的核心是一个while(1)循环,在循环中它将会调用schedule函数以便在运行队列中有新进程加入时切换到该新进程上。

  • 相关阅读:
    温故而知新汇总贴
    温故而知新—heap
    温故而知新--hashtable
    温故而知新-set
    温故而知新——map
    温故而知新----stack
    找工作的时候我们改准备些什么
    js瀑布流布局
    js小游戏---智力游戏
    原生js完成拼图小游戏
  • 原文地址:https://www.cnblogs.com/zmingh/p/5273370.html
Copyright © 2011-2022 走看看