2026/1/24 8:16:35
网站建设
项目流程
菜鸟教程网站建设,郑州住房城乡建设官网,有那些猎头做单的网站,动漫设计与制作主修课程因为我硬件知识有点欠缺#xff0c;所以碰到硬件相关的都尽量专门写一篇笔记。 物理设备和设备控制器和中断控制器#xff1a;网卡#xff0c;声卡#xff0c;显卡#xff0c;键盘鼠标这些所有都是物理设备#xff0c;而管理这些设备的叫设备控制器。CPU只和设备控制器进…因为我硬件知识有点欠缺所以碰到硬件相关的都尽量专门写一篇笔记。物理设备和设备控制器和中断控制器网卡声卡显卡键盘鼠标这些所有都是物理设备而管理这些设备的叫设备控制器。CPU只和设备控制器进行交互而不关心背后的设备具体如何。这节课中我们主要学习的设备控制器是UART它并不管理具体的某个设备而是在QEMU模拟器的帮助下管理从宿主机传进来的输入数据流和发往宿主机中断的输出数据流。设备控制器能够直接和CPU交互即内核可以从设备控制器输入输出信息。但是设备控制器需要引起CPU关注时它作为中断源必须向中断控制器发送信号中断控制器负责仲裁优先级最后向CPU发起真正的中断。而RISC-V中负责记录和分发中断的组件是PLIC。上面是我们之前已经在中断那里学到过的。现在我们结合一下E1000这里的例子深入一下。E1000接收数据包时产生的中断信号传递过程1.E1000网卡内部当数据包到达时DMA完成描述符写回后中断信号会记录在E1000内部的ICRInterrupt Cause Register寄存器中。只要ICR里有未被清除的位网卡就会持续拉高它连接到PLIC的那根物理导线为高电平。2.PLIC只要E1000拉高了导线PLIC的网关就会立刻感知到。在PLIC的内部有一个Pending Bit Array等待位数组对应E1000的那个比特位会被置为1。哪怕CPU正在关中断PLIC依然会将这个Pending Bit置为1.3.CPU最终感知当CPU开启中断时CPU就会看到一个外部中断请求然后跳转到trap处理程序。在trap处理程序中会调用plic_claim()函数然后PLIC将Pending Bit置零。为什么我们在e1000_recv函数中一次只处理一个数据包可能会导致丢失中断信号void e1000_intr(void) { // 1. 读取 ICR 寄存器看看发生了什么事 // 【关键动作】读取 ICR 会自动清除 E1000 内部的中断标志 // 这相当于告诉网卡“我知道了别吵了把手放下。” int icr regs[E1000_ICR]; // 2. 调用你的接收函数 e1000_recv(); }1.数据到达假设在调用e1000_intr之前qemu瞬间往接收环中塞了5个数据包。E1000网卡检测到数据拉高中断线PLIC看到高电平将对应的Pending Bit置位。2.CPU响应CPU发现Pending位跳转到e1000_intr。Pending Bit被置零e1000_intr函数读取ICR寄存器将中断线拉低此时物理层面上没有任何中断信号了。3.e1000_recv只处理第一个包显然后面包的中断信号全部丢失。为什么批量处理能够避免丢失中断信号1.数据到达和之前相同到达5个数据包。2.CPU响应在PLIC将对应的Pending Bit置零E1000信号线拉低。3.e1000_recv在e1000_recv中由于我们采用的是批量处理的逻辑所以所有的这5个数据包都会被读入。而假如在处理过程中数据包再次到达那么会重新将E1000信号线拉高Pending Bit置位。当CPU处理完这个中断后又能看到下一次中断的信号然后继续处理第二次中断的数据包。总结之所以采用批量处理是因为不论PLIC的Pending Bit还有信号线为高电平还是低电平都只能记录0或1。假如它们能够记录更大的值那么我们就可以在每次一个数据包到达时使intrs然后CPU根据intrs的值来知道有多少次中断信号这样就不会丢失中断信号了。但是由于只能记录0和1所以0和1只能抽象为无数据包和有数据包的简单逻辑而我们的recv函数也只知道有数据包而不知道有多少数据包因此采取批量处理是必然的。推而广之硬件中断对于 CPU 来说只是一个唤醒通知而不是一个精确的任务计数器。作为驱动程序收到通知后必须主动检查并处理所有堆积的任务直到缓冲区为空。