我了解了OS系统的工作原理,并且知道外围设备可以发送OS处理的中断。但是我对它如何实际处理没有任何见识。
当我左右移动鼠标时会发生什么?它是否每毫秒发送一次中断? OS如何处理进程的执行和鼠标定位,尤其是在有一个CPU的情况下?在这种情况下,OS如何有效执行上下文切换?
例如,有3个启动过程。进程1是活动的,进程2和进程3已准备就绪,但处于挂起状态。用户使用进程1中的键盘输入内容。据我了解,OS调度程序可以在等待输入的同时启动进程2或进程3。我认为诀窍在于时机。像处理器一样快,它能够在用户按下之间启动进程2和3。
此外,我将不胜感激任何可以熟悉io的工作原理的文献参考,尤其是在时间和计划方面。
答案 0 :(得分:0)
让我们假设它是某种USB设备。对于USB,您有2层设备驱动程序-USB控制器驱动程序和USB外围设备(键盘,鼠标,操纵杆,触摸板等)驱动程序。 USB外围设备驱动程序要求USB控制器驱动程序定期(例如,每8毫秒)轮询设备,USB控制器驱动程序对此进行设置,而USB控制器硬件进行此轮询(而非软件/驱动程序),以及是否接收到来自USB外围设备,它将IRQ发送回USB控制器驱动程序。
当USB控制器发送IRQ时,它将导致CPU中断正在执行的操作并执行USB控制器驱动程序的IRQ处理程序。 USB控制器驱动程序的IRQ处理程序检查USB控制器的状态,并弄清楚为什么它发送IRQ。并注意到USB控制器从USB外设接收到数据;这样就可以确定哪个USB外设驱动程序负责并将接收到的数据转发到该USB外设的设备驱动程序。
注意:因为花太多时间处理IRQ很不好(因为这可能导致其他更重要的IRQ的处理被推迟),有时IRQ处理程序和更高级别的逻辑之间会有某种分离;这几乎是队列的某种变体,其中IRQ处理程序将通知放在队列中,然后从IRQ处理程序返回,队列上的通知导致稍后执行其他操作。这可能发生在USB控制器驱动程序的中间(例如USB控制器驱动程序的IRQ处理程序做了一些工作,然后创建了一个通知,该通知导致USB控制器驱动程序的其余部分完成了其余工作)。有多种方法可以实现这种“通知队列”(延迟过程调用,消息传递,某种其他形式的通信等),并且不同的操作系统使用不同的方法。
USB外围设备的设备驱动程序(例如键盘驱动程序,鼠标驱动程序等)接收USB控制器驱动程序发送的数据(数据来自通过轮询USB外围设备而获取的USB控制器);并检查该数据。根据数据所包含的内容,USB外设的设备驱动程序可能会构造某种事件,以“操作系统标准”的方式描述发生了什么。这可能很复杂(例如,涉及跟踪设备的过去状态以及用于键盘布局的查找表等)。在任何情况下,都将使用某种形式的“通知队列”将结果事件转发给其他对象(通常是用户空间进程)。这可能与以前使用的“通知队列”相同。但可能会有很大的不同(旨在适应用户空间而不是仅用于内核/设备驱动程序)。
注意:通常,每个支持多任务的OS都提供一种或多种正常进程可以用来相互通信的方式。称为“进程间通信”。有多种可能性-管道,套接字,消息传递等。它们全部与调度交互。例如。一个进程可能需要等待,直到它接收到数据并调用一个函数(例如,从管道中读取,从套接字中读取,或者等待消息,或者..)该函数(如果队列中没有数据要接收)将导致通知调度程序将任务置于“阻止”状态(该任务将不会获得任何CPU时间);当数据到达时,调度程序被告知将任务从“阻塞”状态中退出(这样可以/将再次获得CPU时间)。通常(对于良好的操作系统),每当任务从“阻塞”状态中退出时,调度程序就会决定该任务是否应立即抢占当前正在运行的任务;基于某种任务/线程优先级。换一种说法;如果较低优先级的任务当前正在运行,而较高优先级的任务正在等待接收数据,则当较高优先级的任务接收到数据时,它正在等待调度程序可以立即执行任务切换(从较低优先级的任务到较高优先级的任务)这样优先级较高的任务就可以非常快速地检查接收到的数据(无需等待CPU进行次要工作的时间)。
无论如何;事件(来自USB外设的设备驱动程序)被某物(可能是用户空间中的进程)接收到,很可能导致该进程被阻塞并由调度程序立即给定CPU时间。这是用户空间中“层次结构/事物树”的顶部;树中的每个事物都可以查看接收到的数据,然后将其转发到树中的其他事物(使用相同的进程间通信将数据转发给其他事物)。例如;该“层次结构/事物树”可能在树的顶部具有“会话管理器”,然后在其下方具有“ GUI”,然后在其之下具有多个应用程序窗口。有时,一个事件将被消耗并且不转发给其他事件(例如,如果您按“ alt + tab”,则GUI可能会处理该事件本身,而GUI不会将其转发到当前具有键盘焦点的应用程序窗口)。 / p>
最终,大多数事件将在常规应用程序中结束。普通应用程序通常具有一种语言运行时,该运行时将抽象出操作系统的详细信息,从而使应用程序更易于移植(这样,程序员不必关心其应用程序在哪个OS上运行)。例如,对于Java,Java虚拟机可以将操作系统的事件(通过“ OS特定”通信机制以“ OS特定”格式到达)转换为通用的“ KeyEvent”(并通知任何“ KeyListener”)
整个路径(从驱动程序到应用程序中的功能/方法)可能涉及成千上万行由数百人编写的代码,这些代码分布在许多不同的层上。负责一个程序段(例如GUI)的程序员不必担心其他程序段(例如驱动程序)的程序员会做什么。为此原因;您可能不会找到涵盖所有内容(所有层次)的单一信息源。相反,您将仅找到设备驱动程序开发人员的信息,或者仅找到C ++应用程序开发人员的信息,或者...
这也是为什么没有人能提供比一般概述更多的信息(没有任何特定于操作系统或“特定于层”的详细信息)的原因-他们必须写12本书来提供非常详细的答案。