📄 57.html
字号:
<a name='L109'> !<a href='../S/54.html#L58' title='Defined at 58 in kernel/blk_drv/blk.h.'>IN_ORDER</a> (tmp, tmp->next)) && <a href='../S/54.html#L58' title='Defined at 58 in kernel/blk_drv/blk.h.'>IN_ORDER</a> (req, tmp->next))
<a name='L110'> <b>break</b>;
<a name='L111'> req->next = tmp->next;
<a name='L112'> tmp->next = req;
<a name='L113'> <a href='../S/25.html#L14' title='Defined at 14 in include/asm/system.h.'>sti</a> ();
<a name='L114'><font color='red'>}</font>
<a name='L115'>
<a name='L116'><i><font color='green'>//// 创建请求项并插入请求队列。参数是:主设备号major,命令rw,存放数据的缓冲区头指针bh。</font></i>
<a name='L117'><b>static</b> <b>void</b>
<a name='L118'><a href='../S/57.html#L215' title='Refered from 215 in kernel/blk_drv/ll_rw_blk.c.'>make_request</a> (<b>int</b> major, <b>int</b> rw, <b>struct</b> buffer_head *bh)
<a name='L119'><font color='red'>{</font>
<a name='L120'> <b>struct</b> request *req;
<a name='L121'> <b>int</b> rw_ahead;
<a name='L122'>
<a name='L123'><i><font color='green'>/* WRITEA/READA is special case - it is not really needed, so if the */</font></i>
<a name='L124'><i><font color='green'>/* buffer is locked, we just forget about it, else it's a normal read */</font></i>
<a name='L125'><i><font color='green'>/* WRITEA/READA 是特殊的情况 - 它们并不是必要的,所以如果缓冲区已经上锁,*/</font></i>
<a name='L126'><i><font color='green'>/* 我们就不管它而退出,否则的话就执行一般的读/写操作。 */</font></i>
<a name='L127'><i><font color='green'>// 这里'READ'和'WRITE'后面的'A'字符代表英文单词Ahead,表示提前预读/写数据块的意思。</font></i>
<a name='L128'><i><font color='green'>// 当指定的缓冲区正在使用,已被上锁时,就放弃预读/写请求。</font></i>
<a name='L129'> <b>if</b> (rw_ahead = (<a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> == <a href='../S/31.html#L44' title='Defined at 44 in include/linux/fs.h.'>READA</a> || <a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> == <a href='../S/31.html#L45' title='Defined at 45 in include/linux/fs.h.'>WRITEA</a>))
<a name='L130'> <font color='red'>{</font>
<a name='L131'> <b>if</b> (bh->b_lock)
<a name='L132'> <b>return</b>;
<a name='L133'> <b>if</b> (<a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> == <a href='../S/31.html#L44' title='Defined at 44 in include/linux/fs.h.'>READA</a>)
<a name='L134'> <a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> = <a href='../S/31.html#L42' title='Defined at 42 in include/linux/fs.h.'>READ</a>;
<a name='L135'> <b>else</b>
<a name='L136'> <a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> = <a href='../S/31.html#L43' title='Defined at 43 in include/linux/fs.h.'>WRITE</a>;
<a name='L137'> <font color='red'>}</font>
<a name='L138'><i><font color='green'>// 如果命令不是READ 或WRITE 则表示内核程序有错,显示出错信息并死机。</font></i>
<a name='L139'> <b>if</b> (<a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> != <a href='../S/31.html#L42' title='Defined at 42 in include/linux/fs.h.'>READ</a> && <a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> != <a href='../S/31.html#L43' title='Defined at 43 in include/linux/fs.h.'>WRITE</a>)
<a name='L140'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("Bad block dev command, must be R/W/RA/WA");
<a name='L141'><i><font color='green'>// 锁定缓冲区,如果缓冲区已经上锁,则当前任务(进程)就会睡眠,直到被明确地唤醒。</font></i>
<a name='L142'> <a href='../S/57.html#L58' title='Defined at 58 in kernel/blk_drv/ll_rw_blk.c.'>lock_buffer</a> (bh);
<a name='L143'><i><font color='green'>// 如果命令是写并且缓冲区数据不脏,或者命令是读并且缓冲区数据是更新过的,则不用添加</font></i>
<a name='L144'><i><font color='green'>// 这个请求。将缓冲区解锁并退出。</font></i>
<a name='L145'> <b>if</b> ((<a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> == <a href='../S/31.html#L43' title='Defined at 43 in include/linux/fs.h.'>WRITE</a> && !bh->b_dirt) || (<a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> == <a href='../S/31.html#L42' title='Defined at 42 in include/linux/fs.h.'>READ</a> && bh->b_uptodate))
<a name='L146'> <font color='red'>{</font>
<a name='L147'> <a href='../D/1100.html' title='Multiple defined in 2 places.'>unlock_buffer</a> (bh);
<a name='L148'> <b>return</b>;
<a name='L149'> <font color='red'>}</font>
<a name='L150'>repeat:
<a name='L151'><i><font color='green'>/* we don't allow the write-requests to fill up the queue completely:</font></i>
<a name='L152'><i><font color='green'>* we want some room for reads: they take precedence. The last third</font></i>
<a name='L153'><i><font color='green'>* of the requests are only for reads.</font></i>
<a name='L154'><i><font color='green'>*/</font></i>
<a name='L155'><i><font color='green'>/* 我们不能让队列中全都是写请求项:我们需要为读请求保留一些空间:读操作</font></i>
<a name='L156'><i><font color='green'>* 是优先的。请求队列的后三分之一空间是为读准备的。</font></i>
<a name='L157'><i><font color='green'>*/</font></i>
<a name='L158'><i><font color='green'>// 请求项是从请求数组末尾开始搜索空项填入的。根据上述要求,对于读命令请求,可以直接</font></i>
<a name='L159'><i><font color='green'>// 从队列末尾开始操作,而写请求则只能从队列的2/3 处向头上搜索空项填入。</font></i>
<a name='L160'> <b>if</b> (<a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a> == <a href='../S/31.html#L42' title='Defined at 42 in include/linux/fs.h.'>READ</a>)
<a name='L161'> req = request + <a href='../S/54.html#L23' title='Defined at 23 in kernel/blk_drv/blk.h.'>NR_REQUEST</a>; <i><font color='green'>// 对于读请求,将队列指针指向队列尾部。</font></i>
<a name='L162'> <b>else</b>
<a name='L163'> req = request + ((<a href='../S/54.html#L23' title='Defined at 23 in kernel/blk_drv/blk.h.'>NR_REQUEST</a> * 2) / 3); <i><font color='green'>// 对于写请求,队列指针指向队列2/3 处。</font></i>
<a name='L164'><i><font color='green'>/* find an empty request */</font></i>
<a name='L165'><i><font color='green'>/* 搜索一个空请求项 */</font></i>
<a name='L166'><i><font color='green'>// 从后向前搜索,当请求结构request 的dev 字段值=-1 时,表示该项未被占用。</font></i>
<a name='L167'> <b>while</b> (--req >= request)
<a name='L168'> <b>if</b> (req-><a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> < 0)
<a name='L169'> <b>break</b>;
<a name='L170'><i><font color='green'>/* if none found, sleep on new requests: check for rw_ahead */</font></i>
<a name='L171'><i><font color='green'>/* 如果没有找到空闲项,则让该次新请求睡眠:需检查是否提前读/写 */</font></i>
<a name='L172'><i><font color='green'>// 如果没有一项是空闲的(此时request 数组指针已经搜索越过头部),则查看此次请求是否是</font></i>
<a name='L173'><i><font color='green'>// 提前读/写(READA 或WRITEA),如果是则放弃此次请求。否则让本次请求睡眠(等待请求队列</font></i>
<a name='L174'><i><font color='green'>// 腾出空项),过一会再来搜索请求队列。</font></i>
<a name='L175'> <b>if</b> (req < request)
<a name='L176'> <font color='red'>{</font> <i><font color='green'>// 如果请求队列中没有空项,则</font></i>
<a name='L177'> <b>if</b> (rw_ahead)
<a name='L178'> <font color='red'>{</font> <i><font color='green'>// 如果是提前读/写请求,则解锁缓冲区,退出。</font></i>
<a name='L179'> <a href='../D/1100.html' title='Multiple defined in 2 places.'>unlock_buffer</a> (bh);
<a name='L180'> <b>return</b>;
<a name='L181'> <font color='red'>}</font>
<a name='L182'> <a href='../S/74.html#L219' title='Defined at 219 in kernel/sched.c.'>sleep_on</a> (&wait_for_request); <i><font color='green'>// 否则让本次请求睡眠,过会再查看请求队列。</font></i>
<a name='L183'> <b>goto</b> repeat;
<a name='L184'> <font color='red'>}</font>
<a name='L185'><i><font color='green'>/* fill up the request-info, and add it to the queue */</font></i>
<a name='L186'><i><font color='green'>/* 向空闲请求项中填写请求信息,并将其加入队列中 */</font></i>
<a name='L187'><i><font color='green'>// 请求结构参见(kernel/blk_drv/blk.h,23)。</font></i>
<a name='L188'> req-><a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> = bh->b_dev; <i><font color='green'>// 设备号。</font></i>
<a name='L189'> req->cmd = <a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a>; <i><font color='green'>// 命令(READ/WRITE)。</font></i>
<a name='L190'> req->errors = 0; <i><font color='green'>// 操作时产生的错误次数。</font></i>
<a name='L191'> req->sector = bh->b_blocknr << 1; <i><font color='green'>// 起始扇区。(1 块=2 扇区)</font></i>
<a name='L192'> req->nr_sectors = 2; <i><font color='green'>// 读写扇区数。</font></i>
<a name='L193'> req->buffer = bh->b_data; <i><font color='green'>// 数据缓冲区。</font></i>
<a name='L194'> req->waiting = <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>; <i><font color='green'>// 任务等待操作执行完成的地方。</font></i>
<a name='L195'> req->bh = bh; <i><font color='green'>// 缓冲区头指针。</font></i>
<a name='L196'> req->next = <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>; <i><font color='green'>// 指向下一请求项。</font></i>
<a name='L197'> <a href='../S/57.html#L88' title='Defined at 88 in kernel/blk_drv/ll_rw_blk.c.'>add_request</a> (major + blk_dev, req); <i><font color='green'>// 将请求项加入队列中(blk_dev[major],req)。</font></i>
<a name='L198'><font color='red'>}</font>
<a name='L199'>
<a name='L200'><i><font color='green'>//// 低层读写数据块函数。</font></i>
<a name='L201'><i><font color='green'>// 该函数主要是在fs/buffer.c 中被调用。实际的读写操作是由设备的request_fn()函数完成。</font></i>
<a name='L202'><i><font color='green'>// 对于硬盘操作,该函数是do_hd_request()。(kernel/blk_drv/hd.c,294)</font></i>
<a name='L203'><b>void</b>
<a name='L204'><a href='../R/518.html' title='Multiple refered from 8 places.'>ll_rw_block</a> (<b>int</b> rw, <b>struct</b> buffer_head *bh)
<a name='L205'><font color='red'>{</font>
<a name='L206'> <b>unsigned</b> <b>int</b> major; <i><font color='green'>// 主设备号(对于硬盘是3)。</font></i>
<a name='L207'>
<a name='L208'><i><font color='green'>// 如果设备的主设备号不存在或者该设备的读写操作函数不存在,则显示出错信息,并返回。</font></i>
<a name='L209'> <b>if</b> ((major = <a href='../S/31.html#L49' title='Defined at 49 in include/linux/fs.h.'>MAJOR</a> (bh->b_dev)) >= <a href='../S/54.html#L4' title='Defined at 4 in kernel/blk_drv/blk.h.'>NR_BLK_DEV</a> ||
<a name='L210'> !(blk_dev[major].request_fn))
<a name='L211'> <font color='red'>{</font>
<a name='L212'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("Trying to read nonexistent block-device\n\r");
<a name='L213'> <b>return</b>;
<a name='L214'> <font color='red'>}</font>
<a name='L215'> <a href='../S/57.html#L118' title='Defined at 118 in kernel/blk_drv/ll_rw_blk.c.'>make_request</a> (major, <a href='../D/945.html' title='Multiple defined in 15 places.'>rw</a>, bh); <i><font color='green'>// 创建请求项并插入请求队列。</font></i>
<a name='L216'><font color='red'>}</font>
<a name='L217'>
<a name='L218'><i><font color='green'>//// 块设备初始化函数,由初始化程序main.c 调用(init/main.c,128)。</font></i>
<a name='L219'><i><font color='green'>// 初始化请求数组,将所有请求项置为空闲项(dev = -1)。有32 项(NR_REQUEST = 32)。</font></i>
<a name='L220'><b>void</b>
<a name='L221'><a href='../S/52.html#L172' title='Refered from 172 in init/main.c.'>blk_dev_init</a> (<b>void</b>)
<a name='L222'><font color='red'>{</font>
<a name='L223'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>;
<a name='L224'>
<a name='L225'> <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = 0; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> < <a href='../S/54.html#L23' title='Defined at 23 in kernel/blk_drv/blk.h.'>NR_REQUEST</a>; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++)
<a name='L226'> <font color='red'>{</font>
<a name='L227'> request[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>].<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> = -1;
<a name='L228'> request[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>].next = <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>;
<a name='L229'> <font color='red'>}</font>
<a name='L230'><font color='red'>}</font>
</pre>
<hr>
<a name='BOTTOM'>
<i><font color='green'>/* [<][>]<a href='#L58'>[^]</a><a href='#L221'>[v]</a><a href='#TOP'>[top]</a>[bottom]<a href='../mains.html'>[index]</a><a href='../help.html'>[help]</a> */</font></i>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -