Linux操作系统是如何工作的?破解操作系统的奥秘

时间:2024-10-08 12:05:32

学号:SA12**6112

研究笔记:

1:计算机是怎么样工作的

2:用户态到内核态切换之奥秘解析

3:进程切换之奥秘解析

本博文主要是根据前3篇笔记来总结Linux内核的工作机制。

一:操作系统工作的基础

存储程序计算机

  存储程序计算机最早的是冯.诺伊曼体系结构,即以运算为中心,采用存储程序原理,根据指令顺序执行的计算机。

堆栈机制

  在计算机是怎么样工作的中我们分析了,在系统调用过程中,用户态堆栈的变化,在 用户态到内核态切换之奥秘解析进程切换之奥秘解析中我们分析了内核态堆栈的变化。

进而可以发现堆栈在操作系统的工作中的作用:通过堆栈来保存任务切换过程中的上下文,进而在顺序执行的基础上支持了多任务操作。

中断机制

  通过中断机制,计算机可以改变指令的执行顺序,可以中断来协调处理器和外部设备的工作,进而提高了操作系统的工作效率。

二:Linux内核的工作原理

  Linux内核其实就是一种特殊的软件,夹在硬件和应用程序之间,通过Linux内核中的一些抽象概念(进程、虚拟存储器、文件)向应用程序提供简单一致的机制来控制负责的低级硬件设备。

  那Linux内核具体是怎么工作的呢?

  通过前面3篇研究笔记及结合孟老师上课的内容,现总结如下:

  进程是正在运行的程序的一种抽象,它的工作路径是:用户态-内核态-用户态 反复循环,虽然途中可能会发生进程的切换,但是它总的工作方式不会改变,下面我们来具体总结下这过程的5个阶段:

  第一阶段:进程从用户态切换到内核态 :

     (1)通过读取TR寄存器获得TSS,再根据TSS来获得当前进程的内核栈的栈顶指针sp0和栈段描述符,并用它们装载esp和ss,由控制单元在内核栈中保存当前进程的eflags,cs,ss,eip,esp等寄存器的值,并通过SAVE_ALL来保存其他常用寄存器的值到内核栈。

     (2)用TSS中的内核代码段选择符_KERNEL_CS装载CS寄存器

    用中断或者异常处理程序的第一条指令地址装载EIP寄存器

     (3)跳转到EIP所指示的地址处开始执行内核代码

这部分内核代码详细分析过程请见研究笔记:用户态到内核态切换之奥秘解析

  第二阶段:中断处理

       跳转到EIP所指向的指令处后,开始执行内核程序,从这里开始内核的控制路径,注意事项有:

    (1)在中断处理过程中,允许嵌套。

    (2)在中断处理程序运行期间不能发生进程切换

     (3)在中断处理结束时,检查当前进程描述符中的need_resched数据段,判断其是否为1,如果等于1,则调用schedule进行进程调度和切换。

  第三阶段:进程切换

      通过schedule()函数在运行队列的链表中找到一个进程,并随后通过switch_to宏来进行进程切换。

    (1) 首先切换页全局目录

     (2)切换内核堆栈

      (a)把eflags和ebp寄存器保存到prev内核栈中。

      (b)把esp保存到prev->thread.sp中,eip保存到prev->thread.ip中。

      (c)把next指向的新进程的thread.esp保存到esp中,把next->thread.ip保存到eip中

   (3)切换TSS

      (a) load_sp0(tss, next); 从下一个进程的thread字段中获取它的sp0,并用它来更新TSS中的sp0

      (b) __switch_to_xtra(prev_p, next_p, tss);必要的时候会更新IO权位值。

   详细代码分析请见研究笔记:进程切换之奥秘解析

    第四阶段: 处理挂起信号、虚拟模式等任务

           除了处理进程切换请求,内核此时还会检查是否有信号处理请求和其他工作。

处理完上述任务后,再跳转到restore_all处,恢复被中断的程序。   

  第五阶段: 从内核态返回用户态

  从内核态到用户态主要是执行 restore_all 和 Iret

  RESTORE_ALL:主要是恢复SAVE_ALL时保存在内核栈中的常用寄存器的值

IRET指令:

       主要工作是:(1)用保存在内核栈中的值装载CS、EIP、EFLAGS寄存器

             (2)恢复SS、ESP寄存器的值。

            (3)转到用户态继续执行。

参考资料:3.3版本的内核源码

     深入理解Linux内核(第三版)