分类: LINUX
2007-06-17 23:48:19
访问文件的流程:
论坛上的参考:
用户程序——〉glibc库——〉核心系统调用接口——〉核内处理。
核内处理部分,字符设备比较简单,直接按major号访问到设备驱动程序的file_operations结构read接口。
网络设备和块设备都需要经过中间层,网络设备是协议栈,块设备是文件系统。
相比之下,块设备更复杂,因为文件系统之下的设备驱动还分两层:缓冲管理和具体设备驱动。
分几层
----
VFS
---------------------------
特殊文件系统EXT2与page cache
--------------------------
buffer cache
------------
块设备驱动
------------
-----------------------------------------------
~~VFS~~
从sys_read开始,首先通过文件描述符fd获得file结构,然后调用
if (file->f_op && (read = file->f_op->read) != NULL)
ret = read(file, buf, count, &file->f_pos);
进入特殊文件系统,比如EXT2
-----------------------------------------
~~EXT2与page cache~~
EXT2采用的read是一个比较通用的generic_file_read来读取
该函数调用do_generic_file_read完成了主要的工作。
实际上,这个函数主要对page cache操作。首先会考察在page cache
中是否已经有要读取的页面了,是否已经更新了,如果都没有则要读取
这个页面:
readpage:
/* ... and start the actual read. The read will unlock the page. */
error = mapping->a_ops->readpage(filp, page);
注意到,readpage并没有等到读完就返回了,实际上它只是发出读取请求,真正读完要到下面的:
if (!error) {
...
wait_on_page(page);
...
}
wait_on_page会等到该页面被真正读入完成后才返回,在这期间会睡眠,将cpu让给其它进程。
这里的readpage,以ext2_readpage为例实际上是block_read_full_page,后者进入buffer_cache的
操作
-------------------------------------------------------
~~buffer cache~~
block_read_full_page是一个page到buffer的转换。一般会在将page瓜分成若干个buffer(buffer比page小)
为什么要分成buffer呢?
因为硬件设备i/o是以buffer为单位的,这样可以方便操作。那么有buffer了,为什么文件系统不直接使用buffer,还要page呢?因为在文件系统以及以上的层面对页面操作比较方便,比如mmap等。
block_read_full_page将这个页面里的buffer一一提交:submit_bh,后者调用generic_make_request,
generic_make_request将buffer加入到相应设备的buffer请求队列中,这里“加入”不是简单地加到队列中, 为提高效率,会将一些相邻的扇区的buffer移到一起,这样可以使得设备磁头可以一次读完多个扇区。
OK,请求完成后,就返回了,返回到哪呢?就是上面提到的wai_on_page,也就是到此为止,一个进程
的读取的任务告一段落,
可以睡眠等待。直到等设备读完后唤醒该进程。
--------------------------------------------
~~~设备驱动~~~
略,实际上是我不知道细节,只知道大概机制
--------------------------------------------
进程和设备驱动二者是独立的,异步的。因为不是进程提交读的请求后,设备就马上读取需要的数据,有可能这个时候正在读取其它进程需要的数据。
用睡眠/唤醒机制来“同步”这二者。
问题:
1. readpage()里面的 page参数,是新建的页框或者是不为最新的 page?
这个 page应该在什么队列里呢?或者应该链入哪个队列?
2.我们通过page中新建的buffer和sd卡交互完毕后,是通过page还是buffer和fpga交互来完成加密解密呢?
3. generic_make_request 将相邻的扇区的buffer 移到一起,那么我调用fpga 的时候应该细节到这一步么?我觉得如果是通过buffer