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

📄 9.html

📁 网上一个牛人整理的关于linux内核编译
💻 HTML
📖 第 1 页 / 共 5 页
字号:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (bh) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __remove_from_free_list(bh);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; init_buffer(bh);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bh-&gt;b_dev = dev;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bh-&gt;b_blocknr = block;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bh;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; refill_freelist(size);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto try_again;<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
The real I/O is started by ll_rw_block(). It lives in drivers/block/ll_rw_blk.c.<p>
---------------------------------------------------------------------------------------------------<br>
ll_rw_block(int rw, int nr, struct buffer_head * bhs[]) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; nr; i++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct buffer_head *bh = bhs[i];<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bh-&gt;b_end_io = end_buffer_io_sync;<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submit_bh(rw, bh);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
Here bh-&gt;b_end_io specifies what to do when I/O is finished. In this case:<p>
---------------------------------------------------------------------------------------------------<br>
end_buffer_io_sync(struct buffer_head *bh, int uptodate) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mark_buffer_uptodate(bh, uptodate);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unlock_buffer(bh);<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
So, ll_rw_block() just feeds the requests it gets one by one to submit_bh():<p>
---------------------------------------------------------------------------------------------------<br>
submit_bh(int rw, struct buffer_head *bh) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bh-&gt;b_rdev = bh-&gt;b_dev;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bh-&gt;b_rsector = bh-&gt;b_blocknr * (bh-&gt;b_size &gt;&gt; 9);<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; generic_make_request(rw, bh);<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
So, submit_bh() just passes things along to generic_make_request(), the routine to send I/O requests to block devices:<p>
---------------------------------------------------------------------------------------------------<br>
generic_make_request (int rw, struct buffer_head *bh) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request_queue_t *q;<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q = blk_get_queue(bh-&gt;b_rdev);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q-&gt;make_request_fn(q, rw, bh);<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
Thus, it finds the right queue and calls the request function for that queue.<p>
---------------------------------------------------------------------------------------------------<br>
struct blk_dev_struct {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request_queue_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request_queue;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queue_proc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *queue;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *data;<br>
} blk_dev[MAX_BLKDEV];<p>
request_queue_t *blk_get_queue(kdev_t dev)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return blk_dev[MAJOR(dev)].queue(dev);<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
In our case (/dev/hda), the blk_dev struct was filled by hwif_init (from drivers/ide/ide-probe.c):<br>
and this ide_get_queue() is found in drivers/ide/ide.c:<p>
---------------------------------------------------------------------------------------------------<br>
blk_dev[hwif-&gt;major].data = hwif;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blk_dev[hwif-&gt;major].queue = ide_get_queue;<p>
#define DEVICE_NR(dev)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (MINOR(dev) &gt;&gt; PARTN_BITS)<p>
request_queue_t *ide_get_queue (kdev_t dev) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ide_hwif_t *hwif = (ide_hwif_t *) blk_dev[MAJOR(dev)].data;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &amp;hwif-&gt;drives[DEVICE_NR(dev) &amp; 1].queue;<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
This .queue field was filled by ide_init_queue():<br>
And blk_init_queue() (from ll_rw_blk.c again):<p>
---------------------------------------------------------------------------------------------------<br>
ide_init_queue(ide_drive_t *drive) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request_queue_t *q = &amp;drive-&gt;queue;<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q-&gt;queuedata = HWGROUP(drive);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blk_init_queue(q, do_ide_request);<br>
}<p>
blk_init_queue(request_queue_t *q, request_fn_proc *rfn) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q-&gt;request_fn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = rfn;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q-&gt;make_request_fn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = __make_request;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q-&gt;merge_requests_fn&nbsp;&nbsp;&nbsp; = ll_merge_requests_fn;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
}<br>
---------------------------------------------------------------------------------------------------<p>
Aha, so we found the q-&gt;make_request_fn. Here it is:<p>
---------------------------------------------------------------------------------------------------<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __make_request(request_queue_t *q, int rw, struct buffer_head *bh) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* try to merge request with adjacent ones */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* get a struct request and fill it with device, start,length, ... */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add_request(q, req, insert_here);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!q-&gt;plugged)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q-&gt;request_fn(q);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add_request(request_queue_t *q, struct request *req,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct list_head *insert_here) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list_add(&amp;req-&gt;queue, insert_here);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<p>
---------------------------------------------------------------------------------------------------<p>
When the request has been queued, q-&gt;request_fn is called. What is that? We can see it above - it is do_ide_request() and lives in ide.c.<p>
---------------------------------------------------------------------------------------------------<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do_ide_request(request_queue_t *q) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ide_do_request(q-&gt;queuedata, 0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ide_startstop_t startstop;<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (!hwgroup-&gt;busy) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hwgroup-&gt;busy = 1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drive = choose_drive(hwgroup);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startstop = start_request(drive);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (startstop == ide_stopped)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hwgroup-&gt;busy = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ide_startstop_t<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; start_request (ide_drive_t *drive) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long block, blockend;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct request *rq;<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rq = blkdev_entry_next_request(&amp;drive-&gt;queue.queue_head);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; block = rq-&gt;sector;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; block += drive-&gt;part[minor &amp; PARTN_MASK].start_sect;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT_DRIVE(hwif, drive);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (DRIVER(drive)-&gt;do_request(drive, rq, block));<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
---------------------------------------------------------------------------------------------------<p>
So, in the case of a partitioned disk it is only at this very low level that we add in the starting sector of the partition in order to get an absolute sector.<br>
The first actual port access happened already:<p>
---------------------------------------------------------------------------------------------------<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #define SELECT_DRIVE(hwif,drive) \<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OUT_BYTE((drive)-&gt;select.all,<br>
hwif-&gt;io_ports[IDE_SELECT_OFFSET]);<br>
---------------------------------------------------------------------------------------------------<p>
but this do_request function must do the rest. For a disk it is defined in ide-disk.c, in the ide_driver_t idedisk_driver, and the function turns out to be do_rw_disk().<p>
---------------------------------------------------------------------------------------------------<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ide_startstop_t<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long<br>
block) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (IDE_CONTROL_REG)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OUT_BYTE(drive-&gt;ctl,IDE_CONTROL_REG);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OUT_BYTE(rq-&gt;nr_sectors,IDE_NSECTOR_REG);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (drive-&gt;select.b.lba) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OUT_BYTE(block,IDE_SECTOR_REG);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OUT_BYTE(block&gt;&gt;=8,IDE_LCYL_REG);<br>

⌨️ 快捷键说明

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