课程学习总结报告
目录
结构基础
linux结构
可以大致分为用户态和内核态。内核从本质上看是一种软件——控制计算机的硬件资源,并提供上层应用程序运行的环境。用户态即上层应用程序的活动空间,应用程序的执行必须依托于内核提供的资源,包括CPU资源、存储资源、I/O资源等。
在⽤户态(低级别指令),代码能够掌控的范围会受到限制。
在⾼的执⾏级别下,代码可以执⾏特权指令,访问
任意内存,这时 CPU 的执⾏级别对应的就是内核态,所有的指令包括特权指令都可以
执⾏。
进程地址空间结构
这里要明白几个常识,首先,进程的地址空间包含4个部分:操作系统内核、代码段、数据段和栈段。
出于性能原因,地址空间通常分为两半,一部分由程序使用,一部分是内核的地址空间。内核的内存部分是程序的无法访问的,但内核本身可以读取程序的内存。这是将数据传递给内核函数的方法之一。
代码段:构成程序的可执行文件和库。主可执行文件及其所有库都被加载到进程的地址空间中,因此它们的所有的函数都具有内存地址。
数据段:程序用来存储它正在处理的数据的内存,通常称为堆。例如,这可以用于存储当前正在编辑的文档、正在查看的网页或者正在播放的游戏。
栈段:进程中的每个线程可以共享代码段和数据段,但是都有自己的堆栈段。栈段是一块内存,用于跟踪线程当前正在运行的函数,以及所有父函数 - 被调用以获取当前函数的函数。
从上面的分析中,我们要记住重要的一点,在地址空间中,栈是从高地址向低地址增长的。
调用栈是更通用的“栈(stack)”数据结构的专用版本。栈是用于存储对象的可变大小的结构。可以将新对象添加(“push”)到堆栈的顶部,并且可以从堆栈中移除(“pop”)对象。只有堆栈的顶部可以使用push或pop进行修改。
中断处理
为什么要有中断
处理器的速度一般比外设快得多;因此,只有当外设正真完全准备好了,CPU才会转过来处理外设。中断就是满足上述条件的一种解决方法。
中断和异常的区别
中断是异步的,由硬件产生。异常是同步的,在特殊或是出错的指令执行时由CPU控制单元产生。
中断的产生
- 中断控制器见识IRQ线,对引发信号检查。
- 如果出现信号,把信号转换成对应的中断向量。
- 将向量存放在中断控制器的一个I/O端口,允许CPU通过数据总线读取这个向量。
- 把信号发送到处理器的INTR引脚,即产生一个中断。
- 等待CPU处理。
中断描述符表
中断描述符表(IDT),是一张系统表。
- 每个中断或异常在表中有相应的中断或异常处理程序的入口地址。
- 每个描述符8个字节,共256项,占用2KB
- 内核在允许中断前,必须适当初始化IDT
CPU的正常运行
1.执行指令, cs,eip记录了下一条要执行的指令的逻辑地址。
2. 执行指令之前,CPU控制单元会检查前一条指令运行时是否发生了中断或异常
3. 如果发生了中断或异常:
1. 确定中断或异常的向量i
2. 从idtr寄存器中找到IDT的地址,从IDT中找到第i项
3. 从gdtr寄存器中找到GDT的地址,从GDT找到IDT项中的段选择符所标识的段描述符
4. 确定中断是由授权的发生源发出
4.检查是否发生了特权级变化,一般指是否由用户态变为内核态
1.ss、esp、eflags、cs、eip依次入栈
2.硬件出错码入栈
5.如果发生的是故障,在异常处理后再次执行
中断/异常返回
在中断/异常处理完成后,会执行iret指令:
- 将保存在栈中的值装在cs、eip和eflags寄存器,由出错码就弹出
- 检查处理程序的特权等级,判断是否运行在内核态。如果是,就进行下一步
- 从栈中装载ss和esp,返回原来的栈空间
- 检查段寄存器
中断处理
(1) 发生中断后,CPU执行异常向量vector_irq的代码。
(2)在vector_irq里面,最终会调用中断处理程序总入口函数asm_do_IRQ();并且把中断号irq传进来。根据中断号,找到中断号对应的irq_desc结构。
(3)asm_do_IRQ()根据中断号调用irq_desc[NR_IRQS]数组中的对应数组项中的handle_irq();handle_irq是这个或这组中断的处理函数入口。
(4)handle_irq()会使用chip的成员函数来设置硬件,例如清除中断,禁止中断,重新开启中断等;
(5)handle_irq逐个调用用户在action链表中注册的处理函数。
系统调用
- 应用程序 代码调用系统调用( xyz ),该函数是一个包装系统调用的 库函数 ;
- 库函数 ( xyz )负责准备向内核传递的参数,并触发 软中断 以切换到内核;
- CPU 被 软中断 打断后,执行 中断处理函数 ,即 系统调用处理函数 ( system_call);
- 系统调用处理函数 调用 系统调用服务例程 ( sys_xyz ),真正开始处理该系统调用。
进程管理
进程概念
进程是进程实体 的运行过程,是系统进行资源分配和调度的一 个独立单位
特征:
- 进程控制块(PCB)+程序段+相关的数据段=进程实体
- 动态性
- 并发性
- 独立性
- 异步性
进程的组成
- 进程控制块:进程控制块PCB是名字为task_struct的数据结构,它 称为任务结构体。当一个进程被创建时,系统就为该进程建立一个 task_struct任务结构体。当进程运行结束时,系统撤 消该进程的任务结构体。进程的任务结构体是进程存在的唯一标志。
- 进程上下文:把系统提供给进程的处于动态变化的运行环境总和称为进程上下文。
- 进程栈:linux系统为每个用户进程分配了两个栈:用户栈和内核栈。内核进程只有内核栈,没有用户栈。
- 进程的状态:运行态、可运行态、等待态、暂停态、僵死态。
进程控制
进程链表
为了对给定类型的进程进行有效的搜索,内核维护了几个进程链表。一般进程链表是双向链表。
进程切换
进程切换本质上由两步完成:
- 切换页全局目录以安装一个新的地址空间
- 切换内核态堆栈和硬件上下文,例如:CPU寄存器等
进程创建
linux提供了几个系统调用来创建和终止进程:
fork,vfork,clone来创建新进程
exec执行一个新程序
exit来终止进程
进程撤销
撤销过程分为:
- 进程终止:释放进程占有的大部分资源
- 进程删除:彻底删除进程的所有数据结构
进程调度
进程调度算法:
- 先进先出:总把处理机分配给最先进入就绪队列的进程,一个进程一旦分得处理机便一直执行下去,直到进程完成或阻塞时,才释放处理机。
- 最短CPU运行期优先:从就绪队列中选出一个执行时间最短的进程,分配处理机。
- 最高优先权优先调度算法:总把处理机分配给就绪队列中最高优先级的进程。
- 时间片轮转:进程按照FIFO规则排队,按一定的时间间隔分配处理机。
调度时机
- 进程状态发生变化
- 当前进程时间片用完
- 进程从系统调用返回到用户态
- 中断处理后,进程返回到用户态
Linux进程调度策略
- linux的进程调度是基于优先级的调度。进程的优先级是动态的,避免了进程饥饿。
- linux进程分为普通进程和实时进程,实时进程的优先级高于普通进程。实时进程的优先级范围为1~99
- 普通进程采用普通进程的时间片轮转算法
- 实时进程采用实时进程的先进先出或实时进程的时间片轮转算法
时钟
ps:这里学得确实比较菜。。。
时钟类型
时钟中断源
相对时间和墙上时间
驱动基础
ps:这里的代码看得太晕了。。。不知道该看什么了。。。
字符设备的打开
字符设备文件的打开:
系统调用open打开一个字符设备时,通过系统调用sys_open进入内核空间。在内核空间将主要由do_sys_open函数负责发起整个设备文件打开操作,它首先要获得该设备文件所对应的inode,然后调用其中的i_fop函数,对字符设备节点的inode而言,i_fop函数就是chrdev_open。Chrdev_open根据设备号,在字符设备驱动模型中查找对应的驱动程序。设置inode->i_cdev,指向找到的cdev;将inode添加到cdev->list的链表中。使用cdev的ops设置file对象的f_op,如果ops中定义了open方法,则调用该open方法,返回。执行完chrdev_open()后,file对象(filp文件描述符)的f_op指向cdev的ops(file_operations),因而此后对设备进行的read\write等操作,就会执行cdev的相应操作(根据filp中的f_op就可以调用到该文件所对应的设备驱动上实现的函数)
文件系统
ps:这里就只能看重点强调了。。。
文件打开和关闭
应用程序对open ( )的调用将引起内核调用服务例程sys_open ( )函数,该函数接收的参数为:要打开文件的路径名和访问模式等。该系统调用成功后将返回一个文件描述符,也就是文件对象指针数组的一个索引;系统调用不成功时返回-1。
用户程序通过close ( )系统调用关闭打开的文件,该函数接收的参数为要关闭文件的文件描述符。内核服务例程为sys_close ( )函数。
VFS的作用
虚拟文件系统(Virtual File System, 简称 VFS), 是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个 抽象功能,允许不同的文件系统共存。系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。
为了能够支持各种实际文件系统,VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据 结构;同时实际文件系统也提供 VFS 所期望的抽象接口和数据结构,将自身的诸如文件、目录等概念在形式 上与VFS的定义保持一致。换句话说,一个实际的文件系统想要被 Linux 支持,就必须提供一个符合VFS标准 的接口,才能与 VFS 协同工作。实际文件系统在统一的接口和数据结构下隐藏了具体的实现细节,所以在VFS 层和内核的其他部分看来,所有文件系统都是相同的。
fd的定义
为什么read一个文件之前一定要open一个文件
用户进程在读/写一个文件之前必须先打开这个文件。所谓打开文件实质上是在进程与文件之间建立连接,而打开文件描述符唯一地标识着这个连接。
同一个进程,打开两个不同文件,返回的两个fd一不一样
内核中,对应于每个进程都有一个文件描述符表,表示这个进程打开的所有文件。文件描述表中每一项都是一个指针,指向一个用 于描述打开的文件的数据块———file对象,file对象中描述了文件的打开模式,读写位置等重要信息,当进程打开一个文件时,内核就会创建一个新的file对象。需要注意的是,file对象不是专属于某个进程的,不同进程的文件描述符表中的指针可以指向相同的file对象,从而共享这个打开的文件。file对象有引用计数,记录了引用这个对象的文件描述符个数,只有当引用计数为0时,内核才销毁file对象,因此某个进程关闭文件,不影响与之共享同一个file对象的进程。
最后,预言一波
押5个大题
- 系统调用的过程
- 中断处理流程
- 字符设备文件的打开
- linux的启动
- 挂载的整个过程
押中了,记得点赞。。。。