首页 理论教育 操作系统实现:设备请求控制块

操作系统实现:设备请求控制块

时间:2023-10-21 理论教育 版权反馈
【摘要】:设备请求控制块是Hello China的IO管理框架中的核心数据结构(对象),该对象用来跟踪所有对设备的请求操作,一般由IOManager创建,然后通过设备驱动程序提供的服务函数传递给设备驱动程序。一般情况下,设备驱动程序可能维护了多个IO请求任务,这些IO请求任务使用DRCB对象进行跟踪,并被设备驱动程序以队列的形式进行维护。在HelloChina的当前版本实现中,暂不支持IO请求的取消服务。

操作系统实现:设备请求控制块

设备请求控制块(Device Request Control Block,DRCB)是Hello China的IO管理框架中的核心数据结构(对象),该对象用来跟踪所有对设备的请求操作,一般由IOManager创建,然后通过设备驱动程序提供的服务函数(比如DeviceRead、DeviceWrite等)传递给设备驱动程序。设备驱动程序根据DRCB里面的参数确定本次操作的一些特定数据,比如设备读取的开始地址、读取数据的长度以及数据读取后应存放的缓冲区位置等。DRCB是贯穿Hello China设备管理框架的核心数据结构。

该对象(数据结构)的定义如下。

在这个对象的定义中,大多数成员意义很明确,下列三个数据成员需要着重说明一下。

●WaitForCompletion

●OnCompletion

●OnCancel

它们都是函数指针,指向了驱动程序管理框架实现的三个函数,这三个函数分别被驱动程序调用。其中,第一个函数(WaitForCompletion)用于等待请求的操作完成,比如,设备驱动程序根据DRCB对象提供的信息,提交了一个物理设备读取请求,由于这个物理设备的执行速度比CPU慢很多,因此,设备驱动程序不能一直忙等待操作完成,因为这样会浪费很多CPU资源,而是采用中断的方式来等待完成结果。即设备操作完成之后,设备通过中断通知设备驱动程序,然后设备驱动程序再采取进一步的动作。而这个函数(WaitForCompletion)就是用于这个目的,该函数调用后,相应的用户线程(发起IO请求的线程)就会进入阻塞状态,直到对应的操作完成(中断发生)。显然,这样做的好处是大大节约了CPU的资源。

第二个函数是与第一个函数对应的,这个函数由设备驱动程序在完成设备操作后调用,一般情况下是在设备驱动程序的中断处理函数中调用的。这个函数执行后,就会唤醒原来等待IO操作完成的线程(即调用WaitForCompletion函数进入阻塞状态的用户线程),这样当下一次调度的时候,如果这个线程(发起IO请求的线程)的优先级足够高,那么该线程就可以被调度执行。

为了帮助读者进一步理解上述过程和配合关系,下面举一个硬盘读/写的例子。假设用户线程想读取一个文件,于是发起了一个ReadFile的函数调用,后续执行过程如下。

(1)IOManager创建一个DRCB对象,根据ReadFile函数的参数对该对象进行初始化,然后再根据文件对象句柄,找到合适的文件对象(其实是一个设备对象),并调用对应的驱动程序(文件系统驱动程序)提供的DeviceRead函数(以创建的DRCB对象为参数)。

(2)DeviceRead函数根据传递过来的DRCB对象以及设备对象,找到实际的硬盘设备,然后文件系统驱动程序另外创建一个DRCB对象,初始化这个DRCB对象,再以这个新创建的DRCB对象为参数调用硬盘设备对象的DeviceRead函数。注意,这里的DeviceRead函数是由硬盘设备驱动程序提供的,而前一个DeviceRead函数是由文件系统驱动程序提供的。

(3)硬盘设备对象的DeviceRead函数根据传递过来的DRCB对象,初始化一个硬盘读请求事务,并把该DRCB对象放到硬盘驱动程序的等待队列中,然后调用DRCB对象中的WaitForCompletion函数。这时用户线程(即调用ReadFile的线程)会进入阻塞状态。

(4)硬盘驱动器(控制器)执行实际的读操作,完成以后给CPU发一个中断。

(5)中断调度机制根据中断号调用实际的中断处理函数(硬盘驱动程序的中断处理函数),中断处理函数从硬盘控制器读取数据,填充在DRCB指定的缓冲区内,然后把该DRCB对象从等待队列中删除,并调用OnCompletion函数。

(6)OnCompletion函数唤醒等待的用户线程(返回到硬盘驱动程序的DeviceRead函数继续执行),于是DeviceRead函数把从硬盘上读取的数据填充到IOManager发送过来的DRCB对象中,销毁自己创建的DRCB,并返回。

(7)IOManager把从硬盘读取的数据填充到用户线程指定的缓冲区内,然后从ReadFile函数返回。

可以看出,这个过程比较复杂,而且在上面的描述中,省略了数据尺寸不匹配的情况(比如,用户请求4KB的数据,而硬盘驱动程序一次只能读取一个扇区的字节,一般情况下为512B,这种情况下,就需要文件系统驱动程序对原始请求进行分割),因此实际情况可能比上述情况更加复杂。(www.xing528.com)

最后一个函数(OnCancel)用于取消一个IO请求。一般情况下,设备驱动程序可能维护了多个IO请求任务(比如系统中多个线程同时读取同一个硬盘上的文件),这些IO请求任务使用DRCB对象进行跟踪,并被设备驱动程序以队列的形式进行维护。这样可能出现一种情况,就是一个请求任务可能被取消(比如对应的用户线程取消了读取请求),这时设备驱动程序就可以直接把对应的DRCB对象从等待队列中删除,然后调用OnCancel函数,来通知上层模块(IOManager)这个取消请求动作。在HelloChina的当前版本实现中,暂不支持IO请求的取消服务。

需要说明的是,上述三个函数的参数,都是其所在的DRCB对象。比如可以这样调用OnCompletion函数。

由于DRCB对象中包含了发起该IO请求的线程对象(lpKernelThread成员)和一个事件同步对象(lpSynObject),所以这些函数很容易实现线程的阻塞、唤醒等操作。

另外,为了标识DRCB对象的状态,定义了dwDrcbStatus变量,这个变量可以取下列值:

(1)DRCB_STATUS_INITIALIZED:DRCB对象已经被初始化,但尚未被任何线程应用。一个DRCB对象刚被创建后,就被设置为该状态。

(2)DRCB_STATUS_PENDING:DRCB处于排队状态,等待对应的操作完成。比如读取磁盘上的一个数据块,相应的设备操作命令已经发出,但还没有收到最终响应,这个时候,dwDrcbStatus被设置为该值。

(3)DRCB_STATUS_COMPLETED:DRCB对象跟踪的设备请求操作已经成功完成。

(4)DRCB_STATUS_FAILED:DRCB对象跟踪的设备请求操作失败,比如设备在长时间内没有响应,会导致这种情况出现。

(5)DRCB_STATUS_CANCELED:DRCB对象跟踪的设备请求,在完成前被用户取消。比如,用户读取一个硬盘上的数据,驱动程序已经发出请求(这时候,DRCB对象的状态设置为DRCB_STATUS_PENDING),在完成前,用户取消了该读取操作,这时候,操作系统会把该DRCB对象的状态设置为DRCB_STATUS_CANCELED。

另外一个比较重要的成员变量,是dwRequestMode,该变量指明了该DRCB跟踪的请求类型,可以取下列值。

(1)DRCB_REQUEST_MODE_READ:该DRCB对象跟踪的请求类型是一个读取操作,比如读取存储设备上的一块数据。

(2)DRCB_REQUEST_MODE_WRITE:对应写入设备的操作,欲写入设备的具体数据由dwInputLen和lpInputBuffer两个参数指定。

(3)DRCB_REQUEST_MODE_CONTROL:IO Control操作,dwCtrlCommand指明了具体的操作类型,一般情况下,dwCtrlCommand取值的具体含义由设备驱动程序自己定义。

(4)DRCB_REQUEST_MODE_SEEK:在调用DeviceSeek函数的时候,设定该值。

(5)DRCB_REQUEST_FLUSH:在调用DeviceFlush函数的时候,设定该值。

总之,DRCB是从最初的用户请求,到最终的物理设备操作的核心对象。在文件系统的实现中,将会进一步介绍该对象的应用。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈