课程学习总结报告

Linux内核

Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。

 

 

 

 内核是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。

Linux 内核最主要模块有:中断和异常处理、内存管理、进程管理、设备驱动程序、文件系统

一、中断异常处理

(异常具体内容见第三次作业)

https://www.cnblogs.com/lizhen511/p/13133314.html

对于中断处理,也就是硬件中断,特别之处在于IRQ和PIC

每个能发出中断请求的硬件控制设备都有一个指派为IRQ的输出线。所有IRQ都与中断控制器的输入引脚相连。

中断控制器(PIC)通常会执行以下动作:

  1. 监视IRQ线,检查产生的中断信号。
  2. 把接收到的信号转换成对应的中断向量。
  3. 把中断向量存放在中断控制器的一个I/O端口,从而允许CPU通过数据总线读取该向量。
  4. 把产生的信号发送到处理器的INTR管脚,即发出一个中断。
  5. 等待直到CPU确认该中断信号,之后把它写进一个I/O端口,同时清空INRT信号。

二、 进程管理

进程管理主要包括进程创建、进程切换和进程调度。

    1. 进程创建

      • 1号和2号进程的创建
        1号和2号进程的创建是start_kernel初始化到最后由rest_ init通过kernel_thread创建了两个内核线程:⼀个是kernel_init,最终把⽤户态的进程init给启动起来,是所有⽤户进程的祖先;另⼀个是kthreadd内核线程,kthreadd内核线程是所有内核线程的祖先,负责管理所有内核线程。
      • 系统调用fork创建一个进程最终都是通过_do_fork来完成的

        copy_process函数主要完成了调⽤dup_task_struct复制当前进程(⽗进程)描述符task_struct、信息检查、初始化、把进程状态设置为TASK_RUNNING(此时⼦进程置为就绪态)、采⽤写时复制技术逐⼀复制所有其他进程资源、调⽤copy_thread_tls初始化⼦进程内核栈、设置⼦进程pid等。其中最关键的就是dup_task_struct复制当前进程(⽗进程)描述符task_struct和copy_thread_tls初始化⼦进程内核栈。
        ⼦进程创建好了进程描述符、内核堆栈等,就可以通过wake_up_new_task(p)将⼦进程添加到就绪队列,使之有机会被调度执⾏,进程的创建⼯作就完成了,⼦进程就可以等待调度执⾏,⼦进程的执⾏从这⾥设定的ret_from_fork开始。
    2. 进程切换
      为了简便,假设系统只有两个进程,分别是进程0和进程1。进程0由内核启动时初始化执⾏,然后需要进程调度和进程切换,然后开始执⾏进程1。进程切换过程中进程0和进程1的堆栈和相关寄存器的变化过程⼤致如下:

      • pushq %%rbp 保存进程0当前RBP寄存器的值到堆栈;
      • movq %%rsp,%0 保存进程0当前RSP寄存器的值到prev->thread.sp,这时RSP寄存器指向进程的栈顶地址,实际上就是将进程0的栈顶地址保存。
      • movq %2,%%rsp 将进程1的栈顶地址next->thread.sp放⼊RSP寄存器,即RSP改为指向进程1的栈顶地址,完成了进程0和进程1的堆栈切换。
      • movq $1f,%1 保存进程0当前RIP寄存器值到prev->thread.ip,这⾥$1f是指标号1。
      • pushq %3 把即将执⾏的进程1的指令地址next->thread.ip⼊栈,完成pc寄存器值的切换
      • ret 就是将压⼊栈中的next->thread.ip放⼊RIP寄存器,因此CPU开始执行进程1,完成进程的切换
      • popq %%rbp 将进程1堆栈基地址从堆栈中恢复到RBP寄存器中。
    3. 进程调度
      进程调度策略就是从就绪队列中选择⼀个进程的策略⽅法。Linux下的进程调度有2种策略:SCHED_FIFO和SCHED_RR。

      • SCHED_FIFO是针对运行的实时性要求比较高、运行时间短的进程调度策略。这种策略中,系统按照进入队列的先后进行进程的调度。
      • SCHED_RR是针对实时性要求比较高、运行时间比较长的进程调度策略。系统分配给SCHED_RR进程时间片,然后轮循运行这些进程,将时间片用完的进程放入队列的末尾。

三、 文件管理(举例)

Linux支持多种文件系统,包括ext2、ext3、vfat等等。Linux采用虚拟文件系统VFS来达到支持多种文件系统格式的目标。VFS为各类文件系统提供一个统一的操作界面和编程接口。向上提供统一的编程接口,向下对各种文件系统进行兼容

以用户读一个文件为例

当用户点击打开文件时, 会调用库函数中的read()函数, 而在这个函数中会触发软中断指令, CPU正式陷入到内核态, 进程堆栈也会切换到相应的内核态堆栈.接着, 进入异常处理的硬件级流程, 在这个过程中, CPU在栈中保存eflags, cs, 和eip的 内容, 随后进入异常处理的软件级流程, 在这个过程中, CPU会进一步保存上下文. 与这个过程相对应的是: CPU读取idtr寄存器指向的IDT表中的第128项,此时可以得到0x80中断门, 通过这个中断门CPU可以得到中断处理例程. 接着, 中断处理例程会到系统调用表中找到read()函数相对应的VFS虚拟文件系统中的系统调用sys_read()

到达VFS层次后, sys_read()会根据fd在进程打开文件表中找到相应的系统打开文件表(File数据结构), 然后执行系统打开文件表中的file operations中具体的操作.

 

 

 

 

四、 内存管理

在讲进程地址空间时涉及到了内存管理。Linux把进程地址空间分成内核区和用户区两部分。当在内核态申请内存时直接给分配,而进程在用户态申请内存时,只是给了一个新的线性地址空间的一个使用权(打白条),真的要用的时候会产生缺页异常,然后再真的分配。请求调页是一种动态内存分配技术,它把页框的分配推迟到不能再推迟为止。与之相关的分配页框的方式为写时复制:父子进程是共享页框的,当读的时候,不分配新的页框。当写的时候,谁写就给谁分配,两者各自过运行一段时间都就都有了自己的空间。

与进程地址空间有关的全部信息都包含在一个叫做内存描述符的数据结构中,进程只能访问某个有效的线性区,进程的地址空间是线性区链表上所有线性区描述符所规定的集合(通过链表来管理,头部由mmap指向)

image-20200702201540435

五、驱动程序

 

驱动是应用软件和硬件得桥梁,它使得应用软件只需要调用系统软件得API就可以让硬件去完成要求得工作。

 

Linux设备驱动包括字符设备、块设备和网络设备。

 

 

Linux的内核模块机制给内核提供了很强的灵活性,用户通过加载内核模块方便的给内核添加功能,用户同样也可以将内核不需要用的功能卸载。用户通过内核模块机制可以动态的把需要用到的驱动程序动态地加入内核

 

内核模块在内核态运行,并且只能调用和使用内核提供地函数

 

Linux将硬件设备看作是一个特殊的文件来操作,该文件被称为设备文件,系统通过对设备文件的读写等操作,实现对外设的读写等操作。

 

驱动程序是设备文件与直接外设间的桥梁

 

Linux驱动的层次结构如下图所示:

 

字符设备驱动与字符设备之间的关系如下图所示:

 

 

心得体会

孟宁老师教授部分比较基础,大多为实验相关,李春杰老师主要分析源码逻辑,不过由于内容过多,很多内容都直接跳过,总体难度还是比较大,希望以后可以略微减少点内容。当然,这门课程的学习还是很有用的,对于其他课程也很有帮助。

posted on 2020-07-09 16:41  lizhen511  阅读(177)  评论(0编辑  收藏  举报