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

📄 026_pre_fs_c.html

📁 重读linux 2.4.2o所写的笔记
💻 HTML
📖 第 1 页 / 共 2 页
字号:
  <html lang="zh-CN" xmlns:gdoc="">  <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <style type="text/css">/* default css */table {  font-size: 1em;  line-height: inherit;}div, address, ol, ul, li, option, select {   margin-top: 0px;  margin-bottom: 0px;}p {  margin: 0px;}body {        margin: 0px;          padding: 0px;    font-family: Verdana, sans-serif;  font-size: 10pt;  background-color: #ffffff;}h6 { font-size: 10pt }h5 { font-size: 11pt }h4 { font-size: 12pt }h3 { font-size: 13pt }h2 { font-size: 14pt }h1 { font-size: 16pt }blockquote {padding: 10px; border: 1px #DDD dashed }a img {border: 0}div.google_header, div.google_footer {  position: relative;  margin-top: 1em;  margin-bottom: 1em;}/* end default css */  /* default print css */    @media print {    body {       padding: 0;       margin: 0;     }    div.google_header, div.google_footer {      display: block;      min-height: 0;      border: none;    }    div.google_header {      flow: static(header);    }    /* 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_11hd7t62:5">      <table align=center cellpadding=0 cellspacing=0 height=5716 width=802>
  <tbody>
  <tr>
    <td height=5716 valign=top width=802>
      <pre>2006-12-21   <br> </pre>
      <pre>   阅读fs之前普通文件系统包含大量与disk互动的部分.为了更好的理解这些操作.先将IDE<br>驱动的相关部分研究一下. 解决一直有点模糊的问题.</pre>
      <pre>                         <b>大容量磁盘相关问题</b>
                        
  最初的问题来自于BIOS的设计人员和ATA接口的设计人员没有达成一致的意见,BIOS和ATA
为CHS分配的总的字节数,以及cylinder, head, and sector各占用多少bit,都不相同。更严
重的问题是好像谁也没有预见到磁盘的容量增长的如此迅速! 
  </pre>
      <pre>  先来看看各种借口的容量限制:  <br>BIOS int 13接口:<br>            Cylinder   head     sector   limitation             time reach limitation<br>bits         10         8         6      total 24bits  8.4GB    <br>ATA 接口:  cylinder   head    sector<br>bits         16          4        8     total 28bits  137.4GB   Sept 2001 160 GB Maxtor Diamondmax<br></pre>
      <pre>扩展 int 13 接口:(97年之后的bios基本都支持)<br>bits         8bytes*8  64bit LBA number    9.4 trillion gigabytes !!!!<br>ATA-6 接口:<br>bits         6bytes*8  48bit LBA number    less tan Extended int13,but Large enough!!!</pre>
      <pre>  可以看到,BIOS被设计成最大可寻址8GB, ATA-1-5也只能寻址到137GB。这是设计上的硬伤。<br>这两个限制也由此而来。<br><br>在达到8GB之前值得注意的限制是528MB限制:<br>bios 13 和 ATA-5的联合,old bios 直接使用用户传入的CHS给ATA, BIOS mode-&gt;Normal<br>    Cylinder    head  sector  limitation         time<br>     10           4     6      2^20 = 528MB      being a problem around 1993  <br>    </pre>
      <pre>  为了解决这个问题,BIOS引入了Extended CHS,即ECHS,有些bios中叫large mode. <br>以一个2.95GiB的硬盘为例, 硬件报告的CHS是 6136/16/63<br>                              Cylinders      Heads      Sectors   Capacity      <br>IDE/ATA Limits                 65,536           16       256       128 GiB<br>Hard Disk Logical Geometry      6,136           16       63        2.95 GiB<br>BIOS Translation Factor     divide by 8  multiply by 8<br>BIOS Translated Geometry          767          128       63        2.95 GiB<br>BIOS Int 13h Limits              1024          256       63        7.88GiB<br>    </pre>
      <pre>   突破8G的限制只用使用extended int13+ LBA mode(ATA). 如果在使用LBA模式的情况<br>下还有int 13的程序,则BIOS将CHS直接转换成LBA地址,这个叫assisted LBA. <br>   无论如何,只要使用BIOS无论是ECHS转换还是assisted LBA, 都无法突破8.5 GBlimit.<br>并且还有一个问题值得一提: 最大head 数不是256,而是255,因为dos和window95 不能处理<br>head为256的情况.所以总的限制比8.5GB要稍微少一些. <br>           </pre>
      <pre>   ATA规定,大于8.4 GB 的硬盘应该报告CHS为16383/16/63,这意味着`geometry'过时了,<br>硬盘的总大小不能通过geometry来计算了,只能从IDENTIFY command返回的LBA capacity域<br>来获知. 大于137.4 GB的硬盘应该报告LBA capacity是0xfffffff = 268435455 sectors <br>(137G),正确的disksize在新的48 bit的域中.<br>  </pre>
      <pre>   下面列出linux对大容量磁盘的支持情况:<br>   &gt;8.4 GB     kernel should be 2.0.34 or later.<br>   &gt;33.8 GB    kernel should be 2.0.39/2.2.14/2.3.21 or later.<br>   &gt; 137 GB     kernel should be 2.4.19/2.5.3 or later. <br>   </pre>
      <pre>   检查一个版本的linux是否支持大容量硬盘,可以看函数<font color=#0000ff>do_rw_disk</font> (ide-disk.c).</pre>
      <pre>refrence:<br>1. Large Disk Drives &gt;8.4Gb (in addtion, a IBM doc attached)<br>http://www-oss.fnal.gov/projects/fermilinux/common/faq/old/0009.html</pre>
      <pre>2. PC guid of hard disk<br>   http://www.pcguide.com/ref/hdd/index.htm<br>   </pre>
      <pre>   <br>                        <b>block size的种种问题</b></pre>
      <pre>   分析mm的时候说过do_generic_file_read的几个问题,关键的一点是理解最基本的观点。<br>首先是磁盘上的文件尽量缓存在内存,这样才能更快的读写。缓存在内存中,最基本的单<br>位就是内存页面了,在i386上,常见的大小是4k。<br>   通过缓存读取文件的时候,首先是把用户指定的以字节为单位的offset,size转换成<br>以4k为单位的内存页,这样可以直接拷贝数据给用户。如果文件不在缓存中,就要从磁盘<br>读取,比如通过block_read_full_page从磁盘读取一个page大小的数据。<br>   <br>    文件存储于一个具体的文件系统,而这个文件系统有自己的分配单位,那就是block,<br>比如对于ext2,block就是具体的ext2可以分配的最小单位,常见的ext2的block size是<br>1k,可以为2k,4k,但是不能大于4k(refer. ext2_read_super)。<br>    作为存储在这个ext2上的文件,属于它的所有block纪录在磁文件的inode中,纪录的<br>是每一个block的block number。ext2上bocknumber 从1开始(block0#是boot),最大看磁<br>盘容量了,呵呵。这样一来,就把每个文件,以block size为单位分成了从0开始的block。<br>每个文件都是这样一个线型空间,通过inode的一个数组映射到ext2文件系统上从1开始的<br>block空间去。<br>    <br>    过了这样一个步骤,就要和磁盘打交道。通常这个接口是bread(block#, size).<br>struct buffer_head * bread(kdev_t dev, int block, int size)<br>{<br>	struct buffer_head * bh;</pre>
      <pre>	bh = getblk(dev, block, size); /*bh包含了block#和block的size信息*/<br>	if (buffer_uptodate(bh))<br>		return bh;<br>	ll_rw_block(READ, 1, &amp;bh); /* 传递给硬盘驱动*/<br>	wait_on_buffer(bh);<br>	if (buffer_uptodate(bh))<br>		return bh;<br>	brelse(bh);<br>	return NULL;<br>}<br>   这个函数的意思是按照块大小是size读取块号为block的块. 换一种角度,bread按照文件系<br>统理解磁盘的方式提供一个访问磁盘的接口,块大小由size指定,读取那个块由block指定.至<br>于磁盘怎么划分扇区,就不用操心了.<br></pre>
      <pre>                           <b><font size=3>IDE Driver overview</font></b></pre>
      <pre>   我们从bread入手,看看磁盘驱动如何读取磁盘扇区。上边说了bread,这里从ll_rw_block<br>开始。过程虽然从代码里看很复杂,但是主线并不复杂: 给buffer设置一个回叫函数,等磁盘<br>完成读取后通过这个回叫函数设置bh的uptodate位,同时,如果有任务等待这个bh读取完成则唤醒<br>等待的任务. <br>  提交给磁盘的时候,磁盘将这个操作安排到一个队列,然后对所有请求进行调度,以提高磁盘io<br>速度,然后根据调度的结果执行读取任务.<br><font color=#0000ff>ll_rw_block</font>(int rw, int nr, struct buffer_head * bhs[])<br>{<br>	unsigned int major;<br>	int correct_size;<br>	int i;<br>  /*先进行一系列的检查*/<br>	</pre>
      <pre>	 1. /* Determine correct block size for this device. */<br>	 2.	/* Verify requested block sizes. */<br>	 3. 如果是写操作,看看设备是否容许写<br> <br>  /*接着是为bh设置b_end_io:end_buffer_io_sync,通过这个函数通知等待的进程*/<br>	for (i = 0; i &lt; nr; i++) {<br>		struct buffer_head *bh;<br>		bh = bhs[i];</pre>
      <pre>		/* Only one thread can actually submit the I/O. */<br>		if (test_and_set_bit(BH_Lock, &amp;bh-&gt;b_state))<br>			continue;</pre>
      <pre>		/* We have the buffer lock */<br>		bh-&gt;b_end_io = end_buffer_io_sync;<br>  </pre>
      <pre>     ......... //考虑一些可能存在竞争的情况<br>		</pre>
      <pre>		submit_bh(rw, bh); /*提交申请给磁盘驱动程序*/<br>	}<br>	return;<br>  .... //clean<br>}<br>    </pre>
      <pre>   然后是通过submit_bh给磁盘驱动提交申请:<br>void <font color=#0000ff>submit_bh</font>(int rw, struct buffer_head * bh)<br>{<br>	if (!test_bit(BH_Lock, &amp;bh-&gt;b_state))<br>		BUG();</pre>
      <pre>	set_bit(BH_Req, &amp;bh-&gt;b_state);</pre>
      <pre>	/*<br>	 * First step, 'identity mapping' - RAID or LVM might<br>	 * further remap this.<br>	 * 这里把文件系统定义的block#(size)转化为扇区号<br>	 */<br>	bh-&gt;b_rdev = bh-&gt;b_dev;<br>	bh-&gt;b_rsector = bh-&gt;b_blocknr * (bh-&gt;b_size&gt;&gt;9);</pre>

⌨️ 快捷键说明

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