6.html

来自「linux 0.11中文版 有注释」· HTML 代码 · 共 596 行 · 第 1/4 页

HTML
596
字号
<a name='L268'>      <b>if</b> (!(bh = <a href='../S/6.html#L236' title='Defined at 236 in fs/buffer.c.'>find_buffer</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, block)))
<a name='L269'>        <b>return</b> <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>;
<a name='L270'><i><font color='green'>// 对该缓冲区增加引用计数,并等待该缓冲区解锁(如果已被上锁)。</font></i>
<a name='L271'>      bh-&gt;b_count++;
<a name='L272'>      <a href='../S/6.html#L64' title='Defined at 64 in fs/buffer.c.'>wait_on_buffer</a> (bh);
<a name='L273'><i><font color='green'>// 由于经过了睡眠状态,因此有必要再验证该缓冲区块的正确性,并返回缓冲区头指针。</font></i>
<a name='L274'>      <b>if</b> (bh-&gt;b_dev == <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> &amp;&amp; bh-&gt;b_blocknr == block)
<a name='L275'>        <b>return</b> bh;
<a name='L276'><i><font color='green'>// 如果该缓冲区所属的设备号或块号在睡眠时发生了改变,则撤消对它的引用计数,重新寻找。</font></i>
<a name='L277'>      bh-&gt;b_count--;
<a name='L278'>    <font color='red'>}</font>
<a name='L279'><font color='red'>}</font>
<a name='L280'>
<a name='L281'><i><font color='green'>/*</font></i>
<a name='L282'><i><font color='green'>* Ok, this is getblk, and it isn't very clear, again to hinder</font></i>
<a name='L283'><i><font color='green'>* race-conditions. Most of the code is seldom used, (ie repeating),</font></i>
<a name='L284'><i><font color='green'>* so it should be much more efficient than it looks.</font></i>
<a name='L285'><i><font color='green'>*</font></i>
<a name='L286'><i><font color='green'>* The algoritm is changed: hopefully better, and an elusive bug removed.</font></i>
<a name='L287'><i><font color='green'>*/</font></i>
<a name='L288'><i><font color='green'>/*</font></i>
<a name='L289'><i><font color='green'>* OK,下面是getblk 函数,该函数的逻辑并不是很清晰,同样也是因为要考虑</font></i>
<a name='L290'><i><font color='green'>* 竞争条件问题。其中大部分代码很少用到,(例如重复操作语句),因此它应该</font></i>
<a name='L291'><i><font color='green'>* 比看上去的样子有效得多。</font></i>
<a name='L292'><i><font color='green'>*</font></i>
<a name='L293'><i><font color='green'>* 算法已经作了改变:希望能更好,而且一个难以琢磨的错误已经去除。</font></i>
<a name='L294'><i><font color='green'>*/</font></i>
<a name='L295'><i><font color='green'>// 下面宏定义用于同时判断缓冲区的修改标志和锁定标志,并且定义修改标志的权重要比锁定标志大。</font></i>
<a name='L296'><font color='darkred'>#define</font> <a href='../R/6.html' title='Multiple refered from 2 places.'>BADNESS</a>(bh) (((bh)-&gt;b_dirt&lt;&lt;1)+(bh)-&gt;b_lock)
<a name='L297'><i><font color='green'>//// 取高速缓冲中指定的缓冲区。</font></i>
<a name='L298'><i><font color='green'>// 检查所指定的缓冲区是否已经在高速缓冲中,如果不在,就需要在高速缓冲中建立一个对应的新项。</font></i>
<a name='L299'><i><font color='green'>// 返回相应缓冲区头指针。</font></i>
<a name='L300'><b>struct</b> buffer_head *
<a name='L301'><a href='../R/490.html' title='Multiple refered from 7 places.'>getblk</a> (<b>int</b> dev, <b>int</b> block)
<a name='L302'><font color='red'>{</font>
<a name='L303'>  <b>struct</b> buffer_head *tmp, *bh;
<a name='L304'>
<a name='L305'>repeat:
<a name='L306'><i><font color='green'>// 搜索hash 表,如果指定块已经在高速缓冲中,则返回对应缓冲区头指针,退出。</font></i>
<a name='L307'>  <b>if</b> (bh = <a href='../S/6.html#L261' title='Defined at 261 in fs/buffer.c.'>get_hash_table</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, block))
<a name='L308'>    <b>return</b> bh;
<a name='L309'><i><font color='green'>// 扫描空闲数据块链表,寻找空闲缓冲区。</font></i>
<a name='L310'><i><font color='green'>// 首先让tmp 指向空闲链表的第一个空闲缓冲区头。</font></i>
<a name='L311'>  tmp = free_list;
<a name='L312'>  <b>do</b>
<a name='L313'>    <font color='red'>{</font>
<a name='L314'><i><font color='green'>// 如果该缓冲区正被使用(引用计数不等于0),则继续扫描下一项。</font></i>
<a name='L315'>      <b>if</b> (tmp-&gt;b_count)
<a name='L316'>        <b>continue</b>;
<a name='L317'><i><font color='green'>// 如果缓冲头指针bh 为空,或者tmp 所指缓冲头的标志(修改、锁定)权重小于bh 头标志的权重,</font></i>
<a name='L318'><i><font color='green'>// 则让bh 指向该tmp 缓冲区头。如果该tmp 缓冲区头表明缓冲区既没有修改也没有锁定标志置位,</font></i>
<a name='L319'><i><font color='green'>// 则说明已为指定设备上的块取得对应的高速缓冲区,则退出循环。</font></i>
<a name='L320'>      <b>if</b> (!bh || <a href='../S/6.html#L296' title='Defined at 296 in fs/buffer.c.'>BADNESS</a> (tmp) &lt; <a href='../S/6.html#L296' title='Defined at 296 in fs/buffer.c.'>BADNESS</a> (bh))
<a name='L321'>        <font color='red'>{</font>
<a name='L322'>          bh = tmp;
<a name='L323'>          <b>if</b> (!<a href='../S/6.html#L296' title='Defined at 296 in fs/buffer.c.'>BADNESS</a> (tmp))
<a name='L324'>            <b>break</b>;
<a name='L325'>        <font color='red'>}</font>
<a name='L326'><i><font color='green'>/* and repeat until we find something good */</font></i><i><font color='green'>/* 重复操作直到找到适合的缓冲区 */</font></i>
<a name='L327'>    <font color='red'>}</font>
<a name='L328'>  <b>while</b> ((tmp = tmp-&gt;b_next_free) != free_list);
<a name='L329'><i><font color='green'>// 如果所有缓冲区都正被使用(所有缓冲区的头部引用计数都&gt;0),则睡眠,等待有空闲的缓冲区可用。</font></i>
<a name='L330'>  <b>if</b> (!bh)
<a name='L331'>    <font color='red'>{</font>
<a name='L332'>      <a href='../S/74.html#L219' title='Defined at 219 in kernel/sched.c.'>sleep_on</a> (&amp;buffer_wait);
<a name='L333'>      <b>goto</b> repeat;
<a name='L334'>    <font color='red'>}</font>
<a name='L335'><i><font color='green'>// 等待该缓冲区解锁(如果已被上锁的话)。</font></i>
<a name='L336'>  <a href='../S/6.html#L64' title='Defined at 64 in fs/buffer.c.'>wait_on_buffer</a> (bh);
<a name='L337'><i><font color='green'>// 如果该缓冲区又被其它任务使用的话,只好重复上述过程。</font></i>
<a name='L338'>  <b>if</b> (bh-&gt;b_count)
<a name='L339'>    <b>goto</b> repeat;
<a name='L340'><i><font color='green'>// 如果该缓冲区已被修改,则将数据写盘,并再次等待缓冲区解锁。如果该缓冲区又被其它任务使用</font></i>
<a name='L341'><i><font color='green'>// 的话,只好再重复上述过程。</font></i>
<a name='L342'>  <b>while</b> (bh-&gt;b_dirt)
<a name='L343'>    <font color='red'>{</font>
<a name='L344'>      <a href='../S/6.html#L93' title='Defined at 93 in fs/buffer.c.'>sync_dev</a> (bh-&gt;b_dev);
<a name='L345'>      <a href='../S/6.html#L64' title='Defined at 64 in fs/buffer.c.'>wait_on_buffer</a> (bh);
<a name='L346'>      <b>if</b> (bh-&gt;b_count)
<a name='L347'>        <b>goto</b> repeat;
<a name='L348'>    <font color='red'>}</font>
<a name='L349'><i><font color='green'>/* NOTE!! While we slept waiting for this block, somebody else might */</font></i>
<a name='L350'><i><font color='green'>/* already have added "this" block to the cache. check it */</font></i>
<a name='L351'><i><font color='green'>/* 注意!!当进程为了等待该缓冲块而睡眠时,其它进程可能已经将该缓冲块 */</font></i>
<a name='L352'>  *加入进高速缓冲中,所以要对此进行检查。*/
<a name='L353'><i><font color='green'>// 在高速缓冲hash 表中检查指定设备和块的缓冲区是否已经被加入进去。如果是的话,就再次重复</font></i>
<a name='L354'><i><font color='green'>// 上述过程。</font></i>
<a name='L355'>    <b>if</b> (<a href='../S/6.html#L236' title='Defined at 236 in fs/buffer.c.'>find_buffer</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, block))
<a name='L356'>    <b>goto</b> repeat;
<a name='L357'><i><font color='green'>/* OK, FINALLY we know that this buffer is the only one of it's kind, */</font></i>
<a name='L358'><i><font color='green'>/* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */</font></i>
<a name='L359'><i><font color='green'>/* OK,最终我们知道该缓冲区是指定参数的唯一一块,*/</font></i>
<a name='L360'><i><font color='green'>/* 而且还没有被使用(b_count=0),未被上锁(b_lock=0),并且是干净的(未被修改的)*/</font></i>
<a name='L361'><i><font color='green'>// 于是让我们占用此缓冲区。置引用计数为1,复位修改标志和有效(更新)标志。</font></i>
<a name='L362'>  bh-&gt;b_count = 1;
<a name='L363'>  bh-&gt;b_dirt = 0;
<a name='L364'>  bh-&gt;b_uptodate = 0;
<a name='L365'><i><font color='green'>// 从hash 队列和空闲块链表中移出该缓冲区头,让该缓冲区用于指定设备和其上的指定块。</font></i>
<a name='L366'>  <a href='../S/6.html#L190' title='Defined at 190 in fs/buffer.c.'>remove_from_queues</a> (bh);
<a name='L367'>  bh-&gt;b_dev = <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>;
<a name='L368'>  bh-&gt;b_blocknr = block;
<a name='L369'><i><font color='green'>// 然后根据此新的设备号和块号重新插入空闲链表和hash 队列新位置处。并最终返回缓冲头指针。</font></i>
<a name='L370'>  <a href='../S/6.html#L214' title='Defined at 214 in fs/buffer.c.'>insert_into_queues</a> (bh);
<a name='L371'>  <b>return</b> bh;
<a name='L372'><font color='red'>}</font>
<a name='L373'>
<a name='L374'><i><font color='green'>//// 释放指定的缓冲区。</font></i>
<a name='L375'><i><font color='green'>// 等待该缓冲区解锁。引用计数递减1。唤醒等待空闲缓冲区的进程。</font></i>
<a name='L376'><b>void</b>
<a name='L377'><a href='../R/393.html' title='Multiple refered from 56 places.'>brelse</a> (<b>struct</b> buffer_head *buf)
<a name='L378'><font color='red'>{</font>
<a name='L379'>  <b>if</b> (!<a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>)                     <i><font color='green'>// 如果缓冲头指针无效则返回。</font></i>
<a name='L380'>    <b>return</b>;
<a name='L381'>  <a href='../S/6.html#L64' title='Defined at 64 in fs/buffer.c.'>wait_on_buffer</a> (<a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>);
<a name='L382'>  <b>if</b> (!(<a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>-&gt;b_count--))
<a name='L383'>    <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("Trying to free free buffer");
<a name='L384'>  <a href='../S/74.html#L272' title='Defined at 272 in kernel/sched.c.'>wake_up</a> (&amp;buffer_wait);
<a name='L385'><font color='red'>}</font>
<a name='L386'>
<a name='L387'><i><font color='green'>/*</font></i>
<a name='L388'><i><font color='green'>* bread() reads a specified block and returns the buffer that contains</font></i>
<a name='L389'><i><font color='green'>* it. It returns NULL if the block was unreadable.</font></i>
<a name='L390'><i><font color='green'>*/</font></i>
<a name='L391'><i><font color='green'>/*</font></i>
<a name='L392'><i><font color='green'>* 从设备上读取指定的数据块并返回含有数据的缓冲区。如果指定的块不存在</font></i>
<a name='L393'><i><font color='green'>* 则返回NULL。</font></i>
<a name='L394'><i><font color='green'>*/</font></i>
<a name='L395'><i><font color='green'>//// 从指定设备上读取指定的数据块。</font></i>
<a name='L396'><b>struct</b> buffer_head *
<a name='L397'><a href='../R/390.html' title='Multiple refered from 23 places.'>bread</a> (<b>int</b> dev, <b>int</b> block)
<a name='L398'><font color='red'>{</font>
<a name='L399'>  <b>struct</b> buffer_head *bh;
<a name='L400'>
<a name='L401'><i><font color='green'>// 在高速缓冲中申请一块缓冲区。如果返回值是NULL 指针,表示内核出错,死机。</font></i>
<a name='L402'>  <b>if</b> (!(bh = <a href='../S/6.html#L301' title='Defined at 301 in fs/buffer.c.'>getblk</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, block)))
<a name='L403'>    <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("bread: getblk returned NULL\n");
<a name='L404'><i><font color='green'>// 如果该缓冲区中的数据是有效的(已更新的)可以直接使用,则返回。</font></i>
<a name='L405'>  <b>if</b> (bh-&gt;b_uptodate)
<a name='L406'>    <b>return</b> bh;
<a name='L407'><i><font color='green'>// 否则调用ll_rw_block()函数,产生读设备块请求。并等待缓冲区解锁。</font></i>
<a name='L408'>  <a href='../S/57.html#L204' title='Defined at 204 in kernel/blk_drv/ll_rw_blk.c.'>ll_rw_block</a> (<a href='../S/31.html#L42' title='Defined at 42 in include/linux/fs.h.'>READ</a>, bh);
<a name='L409'>  <a href='../S/6.html#L64' title='Defined at 64 in fs/buffer.c.'>wait_on_buffer</a> (bh);
<a name='L410'><i><font color='green'>// 如果该缓冲区已更新,则返回缓冲区头指针,退出。</font></i>
<a name='L411'>  <b>if</b> (bh-&gt;b_uptodate)
<a name='L412'>    <b>return</b> bh;
<a name='L413'><i><font color='green'>// 否则表明读设备操作失败,释放该缓冲区,返回NULL 指针,退出。</font></i>
<a name='L414'>  <a href='../S/6.html#L377' title='Defined at 377 in fs/buffer.c.'>brelse</a> (bh);
<a name='L415'>  <b>return</b> <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>;
<a name='L416'><font color='red'>}</font>

⌨️ 快捷键说明

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