blk_dev_init()在main.c中调用初始化请求项数组;

ll_rw_block()被其他函数如文件系统中函数调用:

void ll_rw_block(int rw, struct buffer_head * bh)// 参数:rw – READ、READA、WRITE 或WRITEA 命令;bh – 数据缓冲块头指针。

块设备工作流程(粗略):

1)文件设备接口调用底层块设备读写函数ll_rw_block(int rw,buffer_head *bh).这里bh要读的设备号,块号,已经写入bh, rw是读或者写指令

2)ll_rw_block(int rw,buffer_head *bh)取主设备号major,调用make_request(major,rw,bh);

3)make_request(major,rw,bh)申请一个请求项,根据rw和bh相应设置填充req各字段值, 并调用add_request (major + blk_dev, req)插入到设备major的请求队列。

4)add_request (major + blk_dev, req)检查设备等待队列是否为空,为空则把req添加到队列中并马上调用设备的请求执行函数。
对于硬盘,这个函数就是do_hd_request,它将根据请求项的各个字段设置向硬盘发出相应的命令. 如果请求队列不为空,则按照电梯算法把req加到队列中。

ll_rw_block函数返回。整个ll_rw_block()返回到上层调用(缓冲管理部分buffer.c。然后调用进程将执行等待wait_on_buffer(bh);进程切换。

硬盘接受命令后,完成req要求的读/写一个扇区后将发出中断。hd_interrupt(定义于kernel/system_call.s)被执行。调用_do_hd。do_hd是设备当前要调用的中断处理函数的指针。根据当前请求,do_hd_request在调用hd_out向硬盘控制器发命令(如读写或复位等)时根据命令类型指定do_hd为read_intr, write_intr或其它。如果为读,do_hd=read_intr。写则do_hd=write_intr。

read_intr 将判断当前请求项请求读的扇区数是否已经全部读完,如果没有,再次设置do_hd=read_intr,然后返回。如果全部完成,则调用end_request(1)去唤醒等待的进程。然后调用do_hd_request去处理其余请求项。

write_intr 将判断当前请求项请求写的扇区数是否已经写完,如果没有,把一扇区数据复制到硬盘缓冲区内,然后再次设置do_hd=write_intr并返回。如果写完,则调用end_request(1),更新并有效缓存块,然后调用do_hd_request去处理其余请求项。

results matching ""

    No results matching ""