OSK VFS read数据流分析
2011-12-14 16:45
120 查看
1. block_read_full_page(struct page *page, get_block_t *get_block)
其中page是读操作的数据存放的位置, 即OS从硬盘上读取数据将会存放到page中.
2. 为这个page分配buffer_head, head = alloc_page_buffers(page); 每个bh对应文件系统的block.
3. 调用submit_bh(READ, bh); 此时的动作为:
分配BIO. 即:
if (buffer_page(bh))
bio->bi_io_vec[0].bv_buffer = bh_page_data(bh);
else
bio->bi_io_vec[0].bv_buffer = bh_data(bh);
bio->bi_io_vec[0].bv_len = bh->b_size;
bio->bi_vcnt = 1;
bio->bi_idx = 0;
bio->bi_size = bh->b_size;
即数据流为page -> buffer_head -> bio
4. submit_bio(int rw, struct bio *bio) -> generic_make_request -> __make_request -> add_request(q, req);
此时的动作是将此BIO作为一个request的member插入到request_queue中
5. 在将来某个时候, SCSI命令将会执行时, 调用scsi_prep_fn(q,ret)
scsi_init_io SCSI初始化IO操作, 它调用blk_rq_map_sg(req->q, req, cmd->request_buffer) ;此时cmd->request_buffer是数据是
1) 是scatter-gather list
2) 就简单的buffer.
因此, 此时的数据流为page -> buffer_head -> bio -> request -> scsi_cmnd的request_buffer.
6. usb_stor_Bulk_transport -> usb_stor_bulk_transfer_sg -> usb_stor_bulk_transfer_sglist or usb_stor_bulk_transfer_buf ->
对于usb_stor_bulk_transfer_buf,
usb_fill_bulk_urb/usb_stor_msg_common -> usb_submit_urb
在usb_fill_bulk_urb中, urb-> transfer_buffer被设置为srb->request_buffer (注: SRB即前面的CMD)
6. 然后在usb_submit_urb()时, 它调用HCD的usb_hcd_submit_urb(). 后者的动作将会将URB的数据转换成HC的硬件数据, 并将其加入到OHCI/UHCI/EHCI的Queue中, status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
对于OHCI, 它的函数为ohci_urb_enqueue -> td_submit_urb (ohci, urb);
对于bulk传输, 将调用td_fill()根据urb->transfer_dma来设置硬件的TD的buffer pointer, 最终写IO寄存器ohci_writel (ohci, OHCI_BLF, &ohci->regs->cmdstatus);
因此, VFS的读操作的数据流为page -> buffer_head -> bio -> request -> scsi_cmnd的request_buffer -> urb的transfer_buffer/transfer_dma -> 硬件TD.
其中page是读操作的数据存放的位置, 即OS从硬盘上读取数据将会存放到page中.
2. 为这个page分配buffer_head, head = alloc_page_buffers(page); 每个bh对应文件系统的block.
3. 调用submit_bh(READ, bh); 此时的动作为:
分配BIO. 即:
if (buffer_page(bh))
bio->bi_io_vec[0].bv_buffer = bh_page_data(bh);
else
bio->bi_io_vec[0].bv_buffer = bh_data(bh);
bio->bi_io_vec[0].bv_len = bh->b_size;
bio->bi_vcnt = 1;
bio->bi_idx = 0;
bio->bi_size = bh->b_size;
即数据流为page -> buffer_head -> bio
4. submit_bio(int rw, struct bio *bio) -> generic_make_request -> __make_request -> add_request(q, req);
此时的动作是将此BIO作为一个request的member插入到request_queue中
5. 在将来某个时候, SCSI命令将会执行时, 调用scsi_prep_fn(q,ret)
scsi_init_io SCSI初始化IO操作, 它调用blk_rq_map_sg(req->q, req, cmd->request_buffer) ;此时cmd->request_buffer是数据是
1) 是scatter-gather list
2) 就简单的buffer.
因此, 此时的数据流为page -> buffer_head -> bio -> request -> scsi_cmnd的request_buffer.
6. usb_stor_Bulk_transport -> usb_stor_bulk_transfer_sg -> usb_stor_bulk_transfer_sglist or usb_stor_bulk_transfer_buf ->
对于usb_stor_bulk_transfer_buf,
usb_fill_bulk_urb/usb_stor_msg_common -> usb_submit_urb
在usb_fill_bulk_urb中, urb-> transfer_buffer被设置为srb->request_buffer (注: SRB即前面的CMD)
6. 然后在usb_submit_urb()时, 它调用HCD的usb_hcd_submit_urb(). 后者的动作将会将URB的数据转换成HC的硬件数据, 并将其加入到OHCI/UHCI/EHCI的Queue中, status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
对于OHCI, 它的函数为ohci_urb_enqueue -> td_submit_urb (ohci, urb);
对于bulk传输, 将调用td_fill()根据urb->transfer_dma来设置硬件的TD的buffer pointer, 最终写IO寄存器ohci_writel (ohci, OHCI_BLF, &ohci->regs->cmdstatus);
因此, VFS的读操作的数据流为page -> buffer_head -> bio -> request -> scsi_cmnd的request_buffer -> urb的transfer_buffer/transfer_dma -> 硬件TD.
相关文章推荐
- VFS 代码分析(open/read/write)
- read 系统调用剖析 (vfs分析 address_space page cache)
- read 系统调用剖析 (vfs分析 address_space page cache)
- read 系统调用剖析 (vfs分析 address_space page cache)
- read 系统调用剖析 (vfs分析 address_space page cache)
- 达芬奇TI DVSDK之视频数据流过程分析
- ffmpeg 源代码简单分析 : av_read_frame()
- USB命令(请求)和USB描述符分析及usb鼠标枚举数据流分析
- VFS文件系统结构分析(容易理解)
- VFS分析(一)挂载(持续更新)
- 关于 readn、writen 函数--read返回值分析
- 目标文件格式分析工具: ar,nm,objdump,objcopy,readelf 之(nm,objdump,readelf篇)
- 【ffmpeg】试图从raw buffer中读取数据的ff_read_packet 浅显分析
- FFMPeg代码分析:AVPacket结构体和av_read_frame函数
- Storm数据流模型的分析及讨论
- 【技术】C#入门:StreamReader类以及其方法ReadLine,Read,ReadToEnd的分析
- Read_tip_分析文档
- Android Camera数据流分析全程记录(overlay方式)
- Linux VFS分析(二)
- 挑战启动极速(4)---sreadahead分析