⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 034_block_dev_c.html

📁 重读linux 2.4.2o所写的笔记
💻 HTML
📖 第 1 页 / 共 2 页
字号:
    /* used to insert page numbers */    div.google_header::before, div.google_footer::before {      position: absolute;      top: 0;    }    div.google_footer {      flow: static(footer);    }    /* always consider this element at the start of the doc */    div#google_footer {      flow: static(footer, start);    }    span.google_pagenumber {      content: counter(page);    }    span.google_pagecount {      content: counter(pages);    }  }  @page {    @top {      content: flow(header);    }    @bottom {      content: flow(footer);    }  }  /* end default print css */ /* custom css *//* end custom css */  /* ui edited css */    body {    font-family: Verdana;        font-size: 10.0pt;    line-height: normal;    background-color: #ffffff;  }    .documentBG {    background-color: #ffffff;  }  /* end ui edited css */</style>   </head>  <body  revision="dcbsxfpf_7c8gx6m:181">      <div align=center>
  <table align=center border=0 cellpadding=0 cellspacing=0 height=5716 width=802>
    <tbody>
    <tr>
      <td height=5716 valign=top width=802>
        <pre>2007-3-6   <br>   参考资料推荐: 当然是《Linux Device Dri vers 2nd》for 2.4.0 版本的。<br><a href=http://www.xml.com/ldd/chapter/book/ch12.html title="Linux Driver 2nd chaper 12 : load block driver"> Linux Driver 2nd chaper 12 : load block driver</a><br><br> 先读一读chaper12, load block driver, 对于理解这个文件相当的有好处。这里仅罗列些block driver 如何与kernel配合的接口和数据结构。<br>block driver需要先注册自己到<b>blkdevs,</b> 就是这个文件实现的东西,这样kernel可以将此设备以设备文件的方式暴露给app。为了支持数据读写<br>driver必须实现自己的request_queue, 并注册到<b>blk_dev</b>, 这个queue和其操作函数是内核读写块设备的接口。 <br>  如果块设备支持分区,driver驱动还要分配并初始化一个<b>gen_disk, </b>并用register_disk 进行注册(分区探测)。下图是对LDD Chapter12的一<br>点简单的总结。<br>                                                                                                                           <br>                                                                                                                    <br>                                                                             blk_size[][];     ;2M disk size<br>                                                                             blksize_size[][]; ;1k (logic block)     <br>                                                                             hardsect_size[][];;512bytes             <br>                                                                     call    read_ahead[];     ;2 sectors            <br>kernel                         call                                    |     max_readahead[][];                     <br>  register_blkdev(major,*name,   |    blk_init_queue                   |     max_sectors[][];                       <br>        block_device_operations) |      (request_queue_t, request_fn)  |     max_segments[];                        <br>  unregister_blkdev(major,*name) |    blk_cleanup_queue                |  ----------------------------------------- <br>           /.\                   |       (request_queue_t *queue)     \ /    register_disk();                       <br>            |                   \ /                 |                  +          /.\                               <br>            |                    +                  |                 /            |                                <br>            |              sbull_bdops = {         call              /             |                                <br>driver     call    open:   sbull_open,                               '             |                                <br>                   release:sbull_release,                           /             call                              <br>                   ioctl:  sbull_ioctl,                            /                                                <br>                   check_media_change: sbull_check_change,        /                                                 <br>                   revalidate:         sbull_revalidate,          '                                                 <br>                           };                                    /                                                  <br>                             +                                  /                                                   <br>                            / \                                /                                                    <br>                             |                                 /                                                    <br>   <font color=#006600><b>blkdevs</b></font>[] [<font color=#ff0000>this file</font>]    |                                /                                                     <br>        +-----------+        |                               /                                                      <br>        | name+bdops|--------\                              /                                                       <br>        +-----------+                                       /                                                       <br>        |           |                                      |                                                        <br>        +-----------+                                     /                                                         <br>        |           |                                    /                                                          <br>        +-----------+                                    /                                                          <br>                                                        /                                                           <br>                                                       /                                                            <br>        +-----------+                                  `                                                            <br>        |           |                                 /                                                             <br>        +-----------+                                /                                                              <br>                               +-----------------+                                                                  <br>   <font color=#006600><b>blk_dev</b></font>[] (ll_rw_blk.c)  ,.| request_queue_t | sbull_request                                                    <br>        +-----------+   _.-``  | queue_proc      |                                                                  <br>        |queue ops  |-'`       | void  *data;    |                                                                  <br>        +-----------+          +-----------------+                                                                  <br>        |           |                                                                                               <br>        +-----------+                                                                                               <br>        |           |                                                                                               <br>        +-----------+                                                                                               <br>                                                                                                                    <br>                                      _,,,,...----...,,,,_                                                          <br>        +-----------+           _.-'``                    ``'-.,                                                    <br>        |           |         .`                                `.                                                  <br>        +-----------+        |      pd                            |                                                 <br>                              ',     /dev/pda through /dev/pdd  ,-                                                  <br>  <font color=#006600><b>gendisk_head</b></font>-&gt;+----------+    `,,-,,                    _,.-'`                                                    <br>                | major   _,.-'``     ```'''''-----''''```                                                          <br>                | name--`` |       +----------+                                                                     <br>                | max_p    |       |start_sect|                                                                     <br>                | *hd_struct-------|nr_sects  |                                                                     <br>                | *sizes   |       |devfs de  |                                                                     <br>                | ...      |       +----------+                                                                     <br>                |          |       |start_sect|                                                                     <br>                |          |       |nr_sects  |                                                                     <br>                +----------+       |devfs de  |                                                                     <br>                                   +----------+                                                                     <br>                                   |start_sect|                                                                     <br>                                   |nr_sects  |                                                                     <br>                                   |devfs de  |                                                                     <br>                                   +----------+                                                                     <br></pre>
        <pre>&nbsp;<br>  了解了块设备驱动,再回过头来看block_dev.c就容易些。此模块提供了几个功能<br>1)为块设备建立设备文件,文件系统接口<br>struct file_operations def_blk_fops = {<br>	open:		<font color=#006600><b>blkdev_open</b></font>,<br>	release:	<font color=#006600><b>blkdev_close</b></font>,<br>	llseek:		<font color=#006600><b>block_llseek</b></font>,<br>	read:		<font color=#006600><b>block_read</b></font>,<br>	write:		<font color=#006600><b>block_write</b></font>,<br>	fsync:		<font color=#006600><b>block_fsync</b></font>,<br>	ioctl:		<font color=#006600><b>blkdev_ioctl</b></font>,<br>};<br>2)管理blkdevs<br>int <font color=#006600><b> unregister_blkdev</b></font>(unsigned int major, const char * name)<br>int <font color=#006600><b> register_blkdev</b></font>(unsigned int major, const char * name, struct block_device_operations *bdops)<br><br><font color=#006600><br><b>  <br></b></font>3)管理<font color=#006600>block_device</font><br>struct <font color=#006600>block_device</font> *<font color=#006600><b>bdget</b></font>(dev_t dev);  <b>分配 </b>struct <font color=#006600>block_device</font>            <br>void   <font color=#006600><b>bdput</b></font>(struct block_device *bdev)  <b>释放 </b>struct <font color=#006600>block_device</font><br><br>int <font color=#006600><b>blkdev_get</b></font>(struct block_device *bdev, mode_t mode, unsigned flags, int kind)  <b>调用blkdevs的bd_ops-&gt;open</b><br>int <font color=#006600><b>blkdev_put</b></font>(struct block_device *bdev, int kind)                               <b>调用blkdevs的bd_ops-&gt;release</b><br><br>int<font color=#006600> ioctl_by_bdev</font>(struct block_device *bdev, unsigned cmd, unsigned long arg) :block_device-&gt;bd_op-&gt;ioctl<br>void __init <font color=#006600>bdev_init</font>(void)<br>   struct block_device {<br>	struct list_head	<font color=#006600><b>bd_hash</b></font>;<br>	atomic_t		<font color=#006600><b>bd_count</b></font>;<br>/*	struct address_space	<font color=#006600><b>bd_data</b></font>; */<br>	dev_t			<font color=#006600><b>bd_dev</b></font>;  /* not a kdev_t - it's a search key */<br>	atomic_t		<font color=#006600><b>bd_openers</b></font>;<br>	const struct block_device_operations *<font color=#006600><b>bd_op</b></font>;<br>	struct semaphore	<font color=#006600><b>bd_sem</b></font>;	/* open/close mutex */<br>};<br><br><br>4)block dev 的其他杂项操作 <br>    int <font color=#006600>check_disk_change</font>(kdev_t dev)<br>    const struct <font color=#000000>block_device_operations</font> * <font color=#006600>get_blkfops</font>(unsigned int major)<br>5) internal function &amp; misc<br>   <font color=#009900><b>init_once</b></font>: for mem cache obj init <br>   <font color=#009900><b>hash</b></font>: for bdget<br>   <font color=#006600><font color=#000000>static struct block_device</font> *bdfind(dev_t dev, struct list_head *head) </font>: for bdget<br>   int <font color=#006600>get_blkdev_list</font>(char * p)  :一个块设备的列表 <br>   const char * <font color=#009900>bdevname</font>(kdev_t dev)<br><br>这个文件出现了几个有关block device的结构,并且名字也类似,真是够乱的:<br>第一类是把块设备虚拟成文件的接口函数:struct <b>file_operations def_blk_fops</b>。<br>第二类是块设备的操作和名字:数组 <b>blkdevs </b>struct block_device_operations *bdops;<br>还有一类是block_device 的操作函数:也包含了 block_device_operations *bd_op,呵呵有点意思。这个block_device的作用是嘛?搜索一下bdget可以看出些<br>端倪:devfs_read_inode 和 init_special_inode 把结构block_device 注册到inode 中。这样看来这个结构是block dev到普通文件系统的一个桥梁。devfs和<br>普通文件系统中的dev文件就记录这个东西。而def_blk_fops通过block_device成为打开的设备文件的操作函数,够绕!看看init_special_inodevoid就明白了。<br>init_special_inode(struct inode *inode, umode_t mode, int rdev)<br>{<br>	inode-&gt;i_mode = mode;<br>	if (S_ISCHR(mode)) {<br>		inode-&gt;i_fop = &amp;def_chr_fops;<br>		inode-&gt;i_rdev = to_kdev_t(rdev);<br>	} else if (S_ISBLK(mode)) {<br>		inode-&gt;i_fop = &amp;def_blk_fops;<br>		inode-&gt;i_rdev = to_kdev_t(rdev);<br>		inode-&gt;i_bdev = bdget(rdev);<br>	} else if (S_ISFIFO(mode))<br>		inode-&gt;i_fop = &amp;def_fifo_fops;<br>	else if (S_ISSOCK(mode))<br>		inode-&gt;i_fop = &amp;bad_sock_fops;<br>	else<br>		printk(KERN_DEBUG "init_special_inode: bogus imode (%o)\n", mode);<br>}<br><br>而blkdev_get 和 blkdev_put 则绕过了文件系统本身,通过虚拟一个文件来带开和释放一个块设备。比较典型的应用是get_sb_bdev和mount_root:在这些<br>情景下通过open打开一个块设备是很不对头的:这些情景下不对这个块设备进行read 和open操作,而是通过具体的文件系统如 ext2 再通过ll_rw_block来<br>读写块设备。(还是绕)<br><br> 当直接打开一个块设备(比如 dd)时是通过这个文件提供的def_blk_fops的几个接口把块设备虚拟成一个无结构的扇区序列来进行操作。(参考<br> init_special_inode)。<br><br><br> 至于这个文件的具体函数,则不是那么难以理解。值得一读以前分析的file_map.c  这个文件,回顾一下buffer cache 和page cache 的区别与<br>联系。<br> ssize_t block_write(struct file * filp, const char * buf,<br>		    size_t count, loff_t *ppos)<br> ssize_t block_read(struct file * filp, char * buf, size_t count, loff_t *ppos)<br> 这两个函数实现对设备文件的读写,从其调用的分配缓冲区的函数 getblk看过去,就知道,直接dd一个设备的话其缓存于buffer cache。 而以前<br>分析filemap。c 的时候知道,普通文件的内容缓存于page cache,普通文件的元数据缓存于buffer cache。<br> 值得注意的是,先前注册到inode中的i_bdev (block_device),并没有在文件的读写过程中发挥什么作用,去搜索i_bdev就可以理解这个inode中<br>的block_device仅仅是为了open, close这个相关的块设备文件而已。真正有用的是inode-&gt;i_rdev,init_special_inode中当然也没有忘记初始<br>化这个变量。<br>   读写块设备文件,主要的工作是把文件的以byte为单位的(start_pos,len)转换为blk size为单位的读写单元,然后一个工作就是缓存,设备<br>文件的读写靠的是buffer cache。 到分析buffer.c的时候再说罢。<br>  <br>static loff_t block_llseek(struct file *file, loff_t offset, int origin)   没啥说的。<br><br>static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)<br>{<br>	return fsync_dev(dentry-&gt;d_inode-&gt;i_rdev);<br>}<br>注意到 fsync_dev<br>int fsync_dev(kdev_t dev)<br>{<br>	sync_buffers(dev, 0);<br><br>	lock_kernel();<br>	sync_supers(dev);<br>	sync_inodes(dev);<br>	DQUOT_SYNC(dev);<br>	unlock_kernel();<br><br>	return sync_buffers(dev, 1);<br>}<br>注意这是对我们分析的一个印证,和一个设备相关的所有数据缓冲:<br>1)dev相关的buffer cache(以(dev,block)为索引),含有像dd这种应用的缓存:sync_buffers,和普通文件的元数据<br>2)sync_supers(dev); 设备的super block<br>3)sync_inodes(dev); sync设备上所有inode(可能是在不同的sb中)的所有文件数据(包括filemap的数据)。(还包括inode本身,inode也算是文件的元数<br>据,但是inode本身没有在buffer cache中,因为inode不仅仅是一个磁盘上的数据影像,他需要进行转换。见mark_inode_dirty,和inode 的分配释放函数,参考<br>inode.c. sync_supers 道理相同。<br><br><br>剩下的函数真的不用多说了。。。。<br><br>end。<br><br><br><br><br><br><br></pre>
      </td>
    </tr>
    </tbody>
  </table>
</div></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -