我们现在必须放下身段看一看低层的IO操作了,复杂繁琐的外设。
PDP-11/40拥有两种外设:
(1) Block device
(2) Character device
简单说来,Block device以block来单位操作数据,而character device则以character为单位
操作数据。我们本章只讨论block device。
struct bdevsw是block device的“操控开关”,通过这个结构可以对此设置执行各种操作,
它由4个指针组成:
4617: struct bdevsw {
4618: int (*d_open)(); /指向该设备的open函数
4619: int (*d_close)(); /指向该设备的close函数
4620: int (*d_strategy)(); /指向该设备的strategy函数(what’s this?)
4621: int *d_tab; /指向该设备的struct devtab
4622: } bdevsw[ ];
而bdevsw [ ]数组则是unix的block device配置表:
4656: int (*bdevsw[])()
4657: {
4658: &nulldev, &nulldev, &rkstrategy, &rktab, /* rk */
4659: &nodev, &nodev, &nodev, 0, /* rp */
…….
4667: };
对任何block device的操作都通过bdevsw [ ]数组进行——这样做的好处是高层函数可以
以相同的方法处理任何一种block device,即通过为block device配置各自的操作函数,就
屏蔽掉了低层的细节。
在我们讨论的模型中,仅有一种block device,即RK磁盘,而相应的bdevsw [ ]数组仅配置了
一种block设备。其他设备的操作函数为nodev,它将返回一个错误:
6566: nodev()
6567: {
6569: u.u_error = ENODEV;
6570: }
【注】nulldev不同,它是个空操作(refer to 6577行)。
swapdev 是系统定义的用于swap的设备,它的高8个bit称为major device number,将作为该设备
在bdevsw数组内的index,如下所示,本模型中定义的swap设备为RK磁盘:
4696: int swapdev {(0<<8)|0
而低8个bit为minor设备号,与具体设备密切相关,在讲解RK磁盘时我们会讲到。
系统也定义了major和minor,如下所示:
4604: struct {
4605: char d_minor;
4606: char d_major;
4607: };
还有个结构与device有关:
4551: struct devtab
4552: {
4553: char d_active; /* busy flag */
4554: char d_errcnt; /* error count (for recovery) */
4555: struct buf *b_forw; /* first buffer for this dev */
4556: struct buf *b_back; /* last buffer for this dev */
4557: struct buf *d_actf; /* head of I/O queue */
4558: struct buf *d_actl; /* tail of I/O queue */
4559: };
bdevsw结构中的d_tab指针实际上就指向该结构的变量。它记录的其实是设备的“状态”信
息——每个device在系统中都有一个对应的devtab结构,比如RK磁盘驱动器的为“rktab”:
5386: struct devtab rktab;
我们来看一下devtab的各项:
1. d_active:“忙”标记。一般说来,在启动device操作时,应该置1,当操作结束后,置0;
2. d_errcnt;: error count (for recovery);
3.剩下的是4个指向struct buf的指针,可分为两对儿:
(1) d_actf和d_actl
构成了device的任务队列,其中,d_actf指向“对”头;d_actl指向“对”尾。
当os要启动外设操作时,就在队列里添加一项,而外设操作结束后,会删除一项。
(2) b_forw和b_back
缓存区的头和尾。
博客地址:http://blog.csdn.net/cszhao1980
博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html