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->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->b_dev == <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> && bh->b_blocknr == block)
<a name='L275'> <b>return</b> bh;
<a name='L276'><i><font color='green'>// 如果该缓冲区所属的设备号或块号在睡眠时发生了改变,则撤消对它的引用计数,重新寻找。</font></i>
<a name='L277'> bh->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)->b_dirt<<1)+(bh)->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->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) < <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->b_next_free) != free_list);
<a name='L329'><i><font color='green'>// 如果所有缓冲区都正被使用(所有缓冲区的头部引用计数都>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> (&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->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->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->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->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->b_count = 1;
<a name='L363'> bh->b_dirt = 0;
<a name='L364'> bh->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->b_dev = <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>;
<a name='L368'> bh->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>->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> (&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->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->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 + -
显示快捷键?