注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

小白的博客

嵌入式爱好者

 
 
 

日志

 
 

linux块设备驱动框架搭建  

2012-09-21 03:09:44|  分类: 韦东山视频第二轮 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
首先我们先来看一下块设备的大体框架:
linux块设备驱动框架搭建 - 小白 - 小白的博客
 
我们再来说一下块设备的读写的机制:

为了加快对块设备的读写,引入了缓冲区的概念:当读块设备时,首先会去读缓冲区,将可以从缓冲区获得的块数据返回给调用者,而无法从缓冲区获得的块则需要去读具体的块设备,当读出数据后,将数据返回给调用者的同时也会将数据写入缓存,以便下次可以直接读出。同样,当写数据的时候,首先检查缓冲区有没有要写入的块数据,如果不存就先将数据写入缓存,在将来某个时候一起写入块设备!
一个块会对应一个内存缓冲区,这个内存缓冲区用buffer_head来描述!

我们从read函数开始分析,应用层执行read函数会对应到内核空间的sys_read函数,这个函数在内核里面就是:
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
      vfs_read(file, buf, count, &pos);//虚拟文件系统层,是具体文件系统的入口
             file->f_op->read(file, buf, count, pos);//这个read函数是内核实现的
                  do_sync_read
                       filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
                       generic_file_aio_read
                              do_generic_file_read
                                     find_get_page(mapping, index);//到缓存页中去查找
                                     mapping->a_ops->readpage(filp, page);//这个函数会去读写真正的块设备
                                               blkdev_readpage(struct file * file, struct page * page)
                                                       block_read_full_page(page, blkdev_get_block);
                                                              submit_bh(READ, bh);//这里就是提交请求

我们在开看一看写的操作:
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, 
size_t, count)
       vfs_write(file, buf, count, &pos);
               file->f_op->write(file, buf, count, pos);
               do_sync_write
                    filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
                    generic_file_aio_write,
                            __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
                                         generic_file_buffered_write
                                                  generic_perform_write(file, &i, pos);
                                                         a_ops->write_begin
                                                          blkdev_write_begin
                                                                block_write_begin
                                                                       __block_write_begin
                                                                                ll_rw_block(READ, 1, &bh);
                                                                                          submit_bh(rw, bh);//提交
具体的读写块设备的入口是:submit_bh
我们就从这个入口开始分析:
      submit_bh(WRITE, bh);
             struct bio *bio;
             bio = bio_alloc(GFP_NOIO, 1);
             bio->bi_io_vec[0].bv_page = bh->b_page;                 //物理页
             bio->bi_io_vec[0].bv_len = bh->b_size;                    //块的大小
             bio->bi_io_vec[0].bv_offset = bh_offset(bh);            //块相对页的偏移
             bio->bi_vcnt = 1;                                                       //为0表示需要被释放该bio
             bio->bi_idx = 0;
             bio_get(bio);                                                              //详见注释1
             submit_bio(rw, bio);//提交
                   generic_make_request(bio);
                         generic_make_request_checks(bio)
                                  struct request_queue *q = bdev_get_queue(bio->bi_bdev);
                                  q->make_request_fn(q, bio);//这对应一个默认函数:q->make_request_fn = mfn;
                                         blk_queue_bio
                                              elv_merge(q, &req, bio);//采用电梯调度算法进行合并
                                              __blk_run_queue(q);
                                                       q->request_fn(q);//最终调用队列里面的request_fn
  评论这张
 
阅读(1383)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017