课程学习总结报告
总结报告:
一 、 Linux内核
Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。
内核是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
Linux 内核由如下几部分组成:内存管理、进程管理、设备驱动程序、文件系统等。
二、进程管理
进程管理是linux内核中最重要的部分,它保证了程序的正常执行。 在Linux中, 进程是系统资源分配的基本单位,也是使用CPU运行的基本调度单位。它实现了对进程的控制和调度。
进程管理的核心功能大致分为四类:控制,同步,通信,调度。
进程控制包括:进程的创建、进程的终止、进程的阻塞与唤醒;
进程调度包括:先到先服务算法、最短作业优先调度、优先级调度、 轮转法调度、多级队列调度、多级队列反馈调度等。
一个进程的上下文(context)包括进程的状态、有关变量和数据结构的值、机器寄存器的值和PCB以及有关程序、数据等。
一个进程的执行是在进程的上下文中执行。
当正在执行的进程由于某种原因要让出处理机时,系统要做进程上下文切换,以使另一个进程得以执行。
当进行上下文切换时系统要首先检查是否允许做上下文切换(在有些情况下,上下文切换是不允许的,例如系统正在执行某个不允许中断的原语时)。然后,系统要保留有关被切换进程的足够信息,以便以后切换回该进程时,顺利恢复该进程的执行。在系统保留了CPU现场之后,调度程序选择一个新的处于就绪状态的进程、并装配该进程的上下文,使CPU的控制权掌握在被选中进程手中。
系统调用的过程:
- 应用程序代码调用系统调用
xyz
,该函数是一个包装系统调用的库函数xyz
; - 库函数
xyz
负责准备向内核传递的参数,并触发软中断以切换到内核态; - CPU 被软中断打断后,执行中断处理函数 ,即系统调用处理函数
system_call
; - 系统调用处理函数调用系统调用服务例程
sys_xyz
,真正开始处理该系统调用。
三、中断管理
为了处理是处理硬件外设I/O,有了中断机制这个东西。
中断分外部中断(硬件中断)和内部中断(软件中断)。内部中断⼜称为异常(Exception),异常⼜分为故障(fault)和陷阱(trap)。中断(广义)会改变处理器执行指令的顺序,通常与CPU芯片内部或外部硬件电路产生的电信号相对应。中断是异步的:由硬件随机产生,在程序执行的任何时候可能出现;异常是同步的:在(特殊的或出错的)指令执行时由CPU控制单元产生。
系统调用作为一种特殊的中断,就是利⽤陷阱(trap)这种软件中断⽅式主动从⽤户态进⼊内核态的。
此时就不得不牵扯到操作系统的“两把宝剑”进程上下文和中断上下⽂。
进程上下文是把系统提供给进程的处于动态变化的运行环境总和。
中断上下文它是一个内核控制路径,代表了中断发生时正在运行的进程执行。
中断的处理过程:
- 确定中断向量。
- 利用中断向量在IDT中找到对应中断门,在中断门中得到段选择符从而可以从GDT中找到中断服务例程的段基址。
- 确定中断发生的特权级合法(linux只有内核态和用户态两种特权级,此步用来检查中断程序的特权是否低于引起中断的程序的特权,低优先级程序不能引起高优先级程序)
- 检查是否发生特权级变化(用户态陷入内核态,这时候需要设置内核的堆栈),如果发生读取当前程序的tss段(通过tr寄存器读取)来选择新特权级的ss和esp指针,然后保存旧的ss和esp指针。
- 若发生的是故障,用引起异常的指令地址修改cs和eip寄存器的值,以使得这条指令在异常处理结束后能被再次执行。
- 在栈中保存eflags、cs和eip的内容。
- 如果异常产生一个硬件出错码,则将它保存在栈中。
- 装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。这对寄存器值给出中断或者异常处理程序的第一条指定的逻辑地址。
四、文件系统
在Linux中,一切都是文件,通过对文件的定义和操作来控制设备的执行和数据的存储。并且使用VFS虚拟文件系统,实现对多种文件系统的兼容。
要实现操作系统对其它各种不同文件系统的支持,就要将对各种不同文件系统的操作和管理纳入到一个统一的框架中。 对用户程序隐去各种不同文件系统的实现细节,为用户程序提供一个统一的、抽象的、虚拟的文件系统界面,这就是所谓的虚拟文件系统(VFS)。
Linux支持多种文件系统,包括ext2、ext3、 vfat、 ntfs、 iso9660、 jffs、 romfs和nfs等,为了对各类文件系统进行统一管理, Linux引入了虚拟文件系统VFS。
虚拟文件系统 VFS:
- 是一个软件层,用来处理与Unix标准文件系统相关的所有系统调用。
- 是用户应用程序与文件系统实现之间的抽象层能为各种文件系统提供一个通用的、统一的接口
根文件系统的挂载:
1. 准备一个虚拟的文件系统 rootfs,将其初始化为根文件系统
Start_kernel 后调用 vfs_caches_init()初始化 vfs。调用 mnt_init()创建一个虚拟的
rootfs,调用 init_rootfs 将其向内核注册。通过 init_mount_tree 挂载根文件系统。 ./挂载点就形成了。
2.将 initrd 文件加载到内存。在这里分两种情况。
① 格式为 cpio_initrd。
a)直接将其解压到根文件下。
b)执行/init,如果执行成功则加载成功。如果失败则执行 3。如果没有/init 那么执行用户定义的根文件系统。然后执行 3。
②格式为 image_initrd。
a)将其释放到/image_initrd 文件下。
b)在内核下将其复制到/dev/ram0 文件下。
c)如果/dev/ram0 是根文件系统,那么挂载根文件系统,然后执行 3。
d)否则执行 Linuxrc,加载根文件系统的一些驱动等。而后挂载根文件系统,然后执行 3。
3. 执行/sbin/init,/bin/int,/etc/init 等,如果成功则挂载根文件系统成功。
读文件的过程:
-
进程调用库函数向内核发起读文件请求;
-
内核通过检查进程的文件描述符定位到虚拟文件系统的已打开文件列表表项;
-
调用该文件可用的系统调用函数read()。read()函数通过文件表项链接到目录项模块,根据传入的文件路径,在目录项模块中检索,找到该文件的inode;
-
在inode中,通过文件内容偏移量计算出要读取的页;
-
通过inode找到文件对应的address_space;
-
在address_space中访问该文件的页缓存树,查找对应的页缓存结点:
-
如果页缓存命中,那么直接返回文件内容;
-
如果页缓存缺失,那么产生一个页缺失异常,创建一个页缓存页,同时通过inode找到文件该页的磁盘地址,读取相应的页填充该缓存页;重新进行第6步查找页缓存;
-
-
文件内容读取成功。
五、设备驱动程序
设备驱动程序是 Linux 内核的主要部分。和操作系统的其它部分类似,设备驱动程序运行在高特权级的处理器环境中,从而可以直接对硬件进行操作,但正因为如此,任何一个设备驱动程序的错误都可能导致操作系统的崩溃。设备驱动程序实际控制操作系统和硬件设备之间的交互。
设备驱动程序提供一组操作系统可理解的抽象接口完成和操作系统之间的交互,而与硬件相关的具体操作细节由设备驱动程序完成。一般而言,设备驱动程序和设备的控制芯片有关,例如,如果计算机硬盘是 SCSI 硬盘,则需要使用 SCSI 驱动程序,而不是 IDE 驱动程序。
六、时钟管理
x86体系的Linux中,主要用到了三种时钟:实时时钟RTC、时间戳计数器TSC及可编程间隔定时器PIT。
RTC一般自带电池,系统掉电后仍可计时,所以Linux刚启动时使用RTC来获取时间。
TSC精度高,进程时间相关的变量一般采用此时钟值进行记录。
PIT虽然精度没有TSC高,但是可以周期性的产生中断
七、学习体会
通过这门课的学习,让我对Linux操作系统中的中断机制、系统调用、进程管理、IO、文件管理等等概念也有了进一步的认知。之前只是知道Linux的基本操作命令,现在对Linux操作系统底层的实现机制已经有了一定的认识,这让我受益良多。非常感谢孟老师,李老师的细心教导。
可能是因为上网课的原因,总是不如在线下授课效果好,可以随时发言提问,老师也可以积极为我们解答。