亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? (ldd) ch12-加載塊設備驅動程序(轉載).htm

?? Linux設備驅動程序用于開發LINUX
?? HTM
?? 第 1 頁 / 共 4 頁
字號:
          <TD width="8%" height=4>
            <DIV align=center><A href="mailto:joyfire@sina.com"><FONT 
            color=#ffffff>聯系</FONT></A></DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE borderColor=#666666 cellPadding=2 width="90%" align=center border=2>
  <TBODY>
  <TR>
    <TD bgColor=#000000>
      <P align=center><A 
      href="http://211.71.69.201/joyfire/lsdp/index.htm"><FONT color=#ffffff 
      size=2>目錄頁</FONT></A> | <A 
      href="http://211.71.69.201/joyfire/lsdp/14.htm"><FONT color=#ffffff 
      size=2>上一頁</FONT></A> | <A 
      href="http://211.71.69.201/joyfire/lsdp/16.htm"><FONT color=#ffffff 
      size=2>下一頁</FONT></A></P>
      <P align=center><FONT face=黑體 color=#ffffff size=6>(LDD) 
      Ch12-加載塊設備驅動程序(轉載) </FONT></P><SPAN 
      style="LINE-HEIGHT: 1; LETTER-SPACING: 0pt"><FONT color=#ffffff size=3>
      <P>發信人:&nbsp;Altmayer&nbsp;(alt),&nbsp;信區:&nbsp;GNULinux<BR>標&nbsp;&nbsp;題:&nbsp;(LDD)&nbsp;Ch12-加載塊設備驅動程序(轉載)<BR>發信站:&nbsp;飲水思源&nbsp;(2001年12月13日08:57:39&nbsp;星期四),&nbsp;站內信件<BR>&nbsp;<BR>【&nbsp;以下文字轉載自&nbsp;<FONT 
      color=#00ff00>UNIXpost&nbsp;</FONT>討論區&nbsp;】<BR>【&nbsp;原文由<FONT 
      color=#00ff00>&nbsp;altmayer.bbs@bbs.nju.edu.cn,</FONT>&nbsp;所發表&nbsp;】<BR>&nbsp;<BR>【&nbsp;以下文字轉載自&nbsp;<FONT 
      color=#00ff00>altmayer&nbsp;</FONT>的信箱&nbsp;】<BR>&nbsp;<BR>第十二章&nbsp;加載塊設備驅動程序<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>正如在第一章“Linux核心簡介”中“設備與模塊的分類”中所概述的一樣,Unix的設備<BR>驅動程序并不僅限于字符設備。本章就來介紹一下第二大類的設備驅動程序——塊設備<BR>驅動程序。所謂面向塊的設備是指數據傳輸是以塊為單位的(例如軟盤和硬盤),這里<BR>硬件的塊一般被稱作“扇區(Sector)”。而名詞“塊”常用來指軟件上的概念:驅動<BR>程序常常使用1KB大小的塊,即使扇區大小為512字節。<BR>&nbsp;<BR>在這一章,我們將來構造一個全特征的塊設備驅動程序sbull(Simple&nbsp;Block&nbsp;Utility<BR>for&nbsp;Loading&nbsp;Localities)。這個驅動程序與scull類似,也是使用計算機的內存作為硬<BR>件設備。換句話說,它是一個RAM-disk的驅動程序。sbull可以在任何Linux計算機上執<BR>行(不過我只在有限的幾個平臺上作過測試)。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>行(不過我只在有限的幾個平臺上作過測試)。<BR>&nbsp;<BR>注冊驅動程序<BR>&nbsp;<BR>和字符設備驅動程序類似,核心里的塊設備驅動程序也是由一個主設備號來標識。用來<BR>對其進行注冊和取消注冊的函數是:<BR>&nbsp;<BR>int&nbsp;register_blkdev(unsigned&nbsp;int&nbsp;major,&nbsp;const&nbsp;char*name,&nbsp;struct<BR>file_operations&nbsp;*fops)<BR>&nbsp;<BR>int&nbsp;unregister_blkdev(unsigned&nbsp;int&nbsp;major,&nbsp;const&nbsp;char*name);<BR>&nbsp;<BR>參數的含義與字符設備驅動程序一樣,對主設備號的動態賦值也類似。因此,一個sbull<BR>設備與scull一樣將自己注冊:<BR>&nbsp;<BR>result=register_blkdev(sbull_major,“sbull”,$sbull_fops);<BR>&nbsp;<BR>if(result&lt;0){<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_WARNING“sbull:can’t&nbsp;get&nbsp;major&nbsp;%d\n”,sbull_major);<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>if&nbsp;(sbull_major==0)&nbsp;&nbsp;sbull_major=result;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*dynamic*/<BR>&nbsp;<BR>major=sbull_major;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*Use&nbsp;“major”later&nbsp;on&nbsp;to&nbsp;save<BR>typing*/<BR>&nbsp;<BR>register_blkdev&nbsp;的fops參數與我們在字符設備驅動程序中使用的類似,為read,write<BR>以及fsync的操作并不要求針對某個驅動程序。通用函數block_read,&nbsp;block_write及blo<BR>ck_fsync被用來代替任何針對某個驅動程序的函數。另外,check_media_change和reval<BR>idate對塊設備驅動程序也有意義,二者都在sbull_fops中定義。<BR>&nbsp;<BR>在sbull中使用的fops結構如下:<BR>&nbsp;<BR>(代碼236)<BR>&nbsp;<BR>通用的讀寫操作被用來獲得較高的性能。通過數據緩沖獲得加速,這在字符設備驅動程<BR>序重中是沒有的。塊設備驅動程序可以被緩沖是因為它們的數據服從于計算機的文件層<BR>次結構,任何應用程序都無法直接訪問,而字符設備驅動程序則不是這樣。<BR>&nbsp;<BR>不過,當緩沖的高速緩存不能滿足一個讀請求或當一個待處理的寫操作要刷新到物理磁<BR>盤上時,驅動程序必須被調用來進行真正的數據傳送。fops結構除了read和write外,并<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>盤上時,驅動程序必須被調用來進行真正的數據傳送。fops結構除了read和write外,并<BR>不帶有入口點,因此,必須要一個額外的結構blk_dev_struct來發出對實際數據傳送的<BR>請求。<BR>&nbsp;<BR>這個結構在&lt;linux/blkdev.h&gt;定義,它有幾個域,但只有第一個域需被驅動程序設置。<BR>下面是這個結構在核心2.0中的定義。<BR>&nbsp;<BR>(代碼237)<BR>&nbsp;<BR>當核心需要為sbull設備產生一個I/O操作時,它便調用函數blk_dev[sbull_major].requ<BR>est_fn。因此這個模塊的初始化函數須設置這個域使其指向它自己的請求函數。這個結<BR>構中的其它域只供核心函數或宏進行內部使用;你不必在你的代碼段中顯式地使用它們<BR>。<BR>&nbsp;<BR>一個塊設備驅動程序模塊與核心的關系見圖12-1。<BR>&nbsp;<BR>除了blk_dev還有幾個數組帶有塊設備驅動程序的信息。這些數組一般由主設備號(有時<BR>也用次設備號)進行索引。它們在drivers/block/ll_rw_block.c中被聲明和描述。<BR>&nbsp;<BR>int&nbsp;blk_size[][];<BR>&nbsp;<BR>這個數組由主設備號和次設備號索引。它以KB為單位描述了每個設備的大小。如果blk_s<BR>ize[major]是NULL,則不對這個設備的大小進行檢查(也就是說,核心可能要求數據傳<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>ize[major]是NULL,則不對這個設備的大小進行檢查(也就是說,核心可能要求數據傳<BR>送通過end_of_device)。<BR>&nbsp;<BR>int&nbsp;blksize_size[][];<BR>&nbsp;<BR>被每個設備所使用的塊的大小,以字節為單位。與上一個數組類似,這個二維數組也是<BR>由主設備號和次設備號索引。如果blksize_size[major]是一個空指針,那么便假設其塊<BR>大小為BLOCK_SIZE(目前是1KB)。塊大小必須是2的冪,因為核心使用移位操作將偏移<BR>量轉換為塊號。<BR>&nbsp;<BR>int&nbsp;hardsect_size[][];<BR>&nbsp;<BR>與其它的一樣,這個數據結構也是由主設備號和次設備號索引。硬件扇區的缺省大小為5<BR>12字節。直到包括2.0.X版本為止,可變扇區大小仍未真正支持,因為一些核心代碼仍舊<BR>假設扇區大小為半KB。不過很可能在2.2版本中會真正實現可變扇區大小。<BR>&nbsp;<BR>int&nbsp;read_ahead[];<BR>&nbsp;<BR>這個數組由主設備號索引,它定義了一個文件被順序讀取時,核心可以提前讀取多少扇<BR>區。在進程請求數據之前將其讀出可以改善系統的性能及總的吞吐率。慢速設備最好指<BR>定一個較大的提前讀的值,而一個快速設備則可以在較小的提前讀的值下工作的很好。<BR>這個提前讀的值越大緩沖高速緩存則需要越多的內存。每個主設備號有一個提前讀的值<BR>,它對所有次設備號有效。這個值可以通過驅動程序的ioctl方法來改變;硬盤驅動程序<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>,它對所有次設備號有效。這個值可以通過驅動程序的ioctl方法來改變;硬盤驅動程序<BR>一般設為8個扇區,對應著4KB。<BR>&nbsp;<BR>sbull設備允許在加載時設置這些值,它們作用于示例驅動程序的所有次設備號。在sbul<BR>l中變量名和它們的缺省值為:<BR>&nbsp;<BR>size=2048(KB)<BR>&nbsp;<BR>由sbull生成的每個ramdisk占兩兆字節,正如系統的缺省值。<BR>&nbsp;<BR>hardsect=512(B)<BR>&nbsp;<BR>sbull扇區大小是常用的半KB值。改變hardsect的值是不允許的。<BR>&nbsp;<BR>如前所述,其它的扇區大小并不被支持。如果你一定要改它,可以將sbull/sbull.c中的<BR>安全檢查去掉。不過請做好發生嚴重的內存崩潰的危險的準備。除非在你嘗試時,已經<BR>加上了對可變扇區大小的支持。<BR>&nbsp;<BR>rahead=2(扇區)<BR>&nbsp;<BR>因為ramdisk是一個快速設備,所以這個缺省提前讀的值比較小。<BR>&nbsp;<BR>sbull設備也允許你選擇一個設備個數進行安裝。devs是設備個數,缺省設為2,表明缺<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>sbull設備也允許你選擇一個設備個數進行安裝。devs是設備個數,缺省設為2,表明缺<BR>省內存使用量為4兆——2個大小為2MB的盤。<BR>&nbsp;<BR>sbull設備的init_module的實現如下(不含主設備號的注冊和錯誤恢復):<BR>&nbsp;<BR>(代碼239)<BR>&nbsp;<BR>相應的清除函數如下所示:<BR>&nbsp;<BR>(代碼240)<BR>&nbsp;<BR>這里,調用fsync_dev是必須的,用以清除核心保存在不同高速緩存中的對設備的所有引<BR>用。事實上,fsync_dev是運行在block--_fsync之后的引擎,它是塊設備的fsync“方法<BR>”。<BR>&nbsp;<BR>頭文件&nbsp;blk.h<BR>&nbsp;<BR>由于塊設備驅動程序的絕大部分是設備無關的,核心的開發者通過把大部分相同的代碼放<BR>在一個頭文件&lt;linux/blk.h&gt;中,來試圖簡化驅動程序的代碼。因此,每個塊設備驅動程<BR>序都必須包含這個頭文件,在&lt;linux/blk.h&gt;中定義的最重要的函數是end_request,它<BR>被聲明為static(靜態)的。讓它成為靜態的,使得不同驅動程序可有一個正確定義的e<BR>nd_request,而不需要每個都寫自己的實現。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>在Linux1.2中,這個頭文件應該用&lt;linux/../../drivers/block/blk.h&gt;來包含。原因在<BR>于當時還不支持自定義的塊設備驅動程序,而這個頭文件最初位于drivers/block源碼目<BR>錄下。<BR>&nbsp;<BR>實際上,blk.h相當不尋常,比如它定義了幾個基于符號MAJOR_NR的符號,而MAJOR_NR必<BR>須由驅動程序在它包含這個頭文件之前聲明。這里,我們再次看到blk.h在設計時并沒有<BR>真正考慮自定義驅動程序。<BR>&nbsp;<BR>看看blk.h,你會發現幾個設備相關的符號是按照MAJOR_NR的值聲明的,也就是說MAJOR_<BR>NR應該提前知道。然而,如果主設備號是動態賦值的,驅動程序無法預知其值,因此也<BR>就不能正確定義MAJOR_NR。如果MAJOR_NR未定義,blk.h就不能設定一些在end_request<BR>中使用的宏。因此,為了讓自定義驅動程序從通用的end_request函數受益,從而避免重<BR>新實現它,驅動程序必須在包含blk.h之前定義MAJOR_NR和其它幾個符號。<BR>&nbsp;<BR>下面的列表描述了一些必須提前定義的&lt;linux/blk.h&gt;中的符號。列表結尾給出了sbull<BR>中使用的代碼。<BR>&nbsp;<BR>MAJOR_NR<BR>&nbsp;<BR>這個符號用來訪問一些數組,特別是blk-_dev和blksize-_size。自定義驅動程序(如sb<BR>ull)不能給這個符號賦一個常量值,可以將其定義(#define)為一個存有主設備號的<BR>變量。對sbull而言,它是sbull-_major。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>變量。對sbull而言,它是sbull-_major。<BR>&nbsp;<BR>DEVICE_NAME<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;被生成的設備名。這個字符串用來從end_request中打印錯誤信息。<BR>&nbsp;<BR>DEVICE_NR(kdev_t&nbsp;device)<BR>&nbsp;<BR>這個符號用來從kdev_t設備號中抽取物理設備的序號。這個宏的值可以是MINOR(device)<BR>或別的表達式。這要依據給設備或分區分配次設備號的常規方式而定。對同一個物理設<BR>備上的所有分區,這個宏應返回同一個設備號——也就是說,DEVICE_NR表達的是磁盤號<BR>,而不是分區號。這個符號被用來聲明CURRENT_DEV,它在request_fn中用來確定被一個<BR>傳送請求訪問的硬件設備的次設備號,可分區設備將在后面“可分區設備”一節中介紹<BR>。<BR>&nbsp;<BR>DEVICE_INTR<BR>&nbsp;<BR>這個符號用來聲明一個指向當前下半部處理程序的指針變量。宏SET_INTR(intr)和CLEAR<BR>_INTR用來給這個變量賦值。當設備可以發出具有不同含義的中斷時,使用多個處理程序<BR>是很方便的。這個主題將在后面“中斷驅動的塊設備驅動程序”一節中討論。<BR>&nbsp;<BR>TIMEOUT_VALUE<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>DEBICE_TIMEOUT<BR>&nbsp;<BR>TIMEOUT_VALUE以記數的方式表達超時,這個超時的值與老計時器之一(特別地指計時器<BR>號DEVICE_TIMEOUT)相關聯。一個驅動程序可以在數據傳送時間太長時,通過調用一個<BR>回調函數來檢測錯誤條件。不過,由于老計時器由一個預賦值的計時器靜態數組組成(<BR>見第六章“時間流”中“核心計時器”一節),一個自定義的驅動程序不能使用它們。<BR>我在sbull中對這兩個符號都未定義,而是用一個新的計時器實現超時。<BR>&nbsp;<BR>DEBICE_NO_RANDOM<BR>&nbsp;<BR>在缺省情況下,函數end_request對系統熵值(即所有隨機性的總量)有所貢獻,這被/d<BR>ev/random所使用。如果一個設備不能對隨機設備貢獻顯著的熵值,DEVICE_NO_RANDOM應<BR>被定義。/dev/random在第九章的“安裝中斷處理程序”中進行了介紹,SA_SAMPLE_RAND<BR>OM也在那兒做了解釋。<BR>&nbsp;<BR>DEVICE_OFF(kdev_t&nbsp;device)<BR>&nbsp;<BR>end_request函數在結束時調用這個宏。例如在軟盤驅動程序中,它調用一個函數,這個<BR>函數負責更新用來控制馬達停轉的一個計時器。如果設備沒有被關掉,那么串DEVICE_OF<BR>F可以被定義為空。sbull不使用DEVICE_OFF。<BR>&nbsp;<BR>DEVICE_ON(kdev_t&nbsp;device)<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>DEVICE_ON(kdev_t&nbsp;device)<BR>&nbsp;<BR>DEVICE_REQUEST<BR>&nbsp;<BR>這些函數實際上并未在Linux的頭文件中使用,所以驅動程序并不需要定義它們。大多數<BR>官方的Linux設備驅動程序聲明這些符號并在內部使用它們,但我在sbull里并沒有使用<BR>它。<BR>&nbsp;<BR>sbull驅動程序以如下的方式聲明這些符號:<BR>&nbsp;<BR>(代碼242)<BR>&nbsp;<BR>頭文件blk.h用上面列出的這些宏定義了一些可以由驅動程序使用的額外的宏,我將在后<BR>續章節里對之進行介紹。<BR>&nbsp;<BR>處理請求<BR>&nbsp;<BR>系統性能的方式排序。這些聯結表中的請求被傳遞個驅動程序的請求函數,由它對鏈接<BR>表中的每個請求執行如下的任務:<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;檢查當前請求的有效性。這個工作由在blk.h中定義的宏INIT_REQUEST完成。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;進行實際的數據傳送。用變量CURRENT(實際上是個宏)可以獲得發出請求的一<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;進行實際的數據傳送。用變量CURRENT(實際上是個宏)可以獲得發出請求的一<BR>些細節。CURRENT是一個指向結構request的指針,我將在下節介紹這個結構的域。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;清除當前的請求。這個操作由靜態函數end_request完成,函數的代碼在blk.h<BR>中。驅動程序向這個函數傳遞一個參數,即成功時為1,失敗時為0。當end_request以參<BR>數0調用時,一個“I/O&nbsp;error”消息會被發給系統日志(通過printk)。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;循環回至開始,消化下一個請求。可以按照程序員的喜好使用一個goto或是一<BR>個for(;;),或者while(1)。<BR>&nbsp;<BR>實踐中,請求函數的代碼如下構造:<BR>&nbsp;<BR>(代碼243)<BR>&nbsp;<BR>盡管這段代碼除了打印消息外什么都沒有做,運行這個函數可以對數據傳送的基本設計<BR>有一個很好的了解。到此為止,代碼中唯一不清楚的地方是CURRENT的確切含義及它的域<BR>,這個我將在下一節介紹。<BR>&nbsp;<BR>我的第一個sbull實現只包含了所示的空代碼。我意在一個“不存在”的設備上構造一個<BR>文件系統,并使用它一會兒,只要數據仍在緩沖高速緩存中。在運行一個象這樣羅嗦的<BR>請求函數時,看看系統日志能幫助你理解緩沖高速緩存是如何工作的。<BR>&nbsp;<BR>在編譯時,定義符號SBULL_EMPTY_REQUEST,那么這個空且羅嗦的函數可以在sbull&nbsp;中運<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>在編譯時,定義符號SBULL_EMPTY_REQUEST,那么這個空且羅嗦的函數可以在sbull&nbsp;中運<BR>行。如果你想理解核心是如何處理不同塊大小的,你可以在insmod命令行上實驗blksize<BR>=。這個空的請求函數通過打印每個請求的細節揭示了內部核心的工作情況。你或許也可<BR>以試試hardsect=,但目前它被關閉了,因為比較危險。(見本章開始時的“注冊驅動程<BR>序”)。<BR>&nbsp;<BR>請求函數的代碼并不顯式地調用return(),因為當列表中的待處理請求耗盡時,INIT-_RE<BR>QUEST會替你完成這個工作。<BR>&nbsp;<BR>執行實際的數據傳送<BR>&nbsp;<BR>為了給sbull構造一個可以工作的數據傳送,讓我們先來看看核心是如何在結構request<BR>中描述一個請求的。這個結構在&lt;linux/blkdev.h&gt;中定義。通過訪問CURRENT的域,驅動<BR>程序可以得到所有為在緩沖高速緩存的物理塊設備之間傳送數據所需要的信息。<BR>&nbsp;<BR>CURRENT是用來訪問當前請求(即被首先服務的那個請求)。正如你可能猜到的,CURREN<BR>T是blk_dev[MAJOR_NR].current_request的縮短形式。<BR>&nbsp;<BR>下面這些當前請求的域包含了請求函數的有用信息:<BR>&nbsp;<BR>kdev_t&nbsp;rq_dev;<BR>&nbsp;<BR>請求所訪問的設備。有本驅動程序所管理的所以設備均被使用同一個請求函數。一個請<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>請求所訪問的設備。有本驅動程序所管理的所以設備均被使用同一個請求函數。一個請<BR>求函數處理所有的次設備號;rq_dev可以被用來取得被操作的次設備。盡管Linux1.2稱<BR>這個域為dev,你仍然可以通過宏CURRENT_DEV來訪問這個域。CURRENT_DEV在我們所討論<BR>的所有版本的核心中是可移植的。<BR>&nbsp;<BR>int&nbsp;cmd;<BR>&nbsp;<BR>這個域是READ或WRITE。<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;sector;<BR>&nbsp;<BR>請求指向的第一個扇區。<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;current_nr_sectors;<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;nr_sectors;<BR>&nbsp;<BR>當前請求的扇區數(大小)。驅動程序應該引用current_nr_sectors,而應該忽略nr_sec<BR>tors(列在這里只是為了完整)。請看下一節“集簇請求”以獲得更多的細節。<BR>&nbsp;<BR>char&nbsp;*buffer<BR>&nbsp;<BR>緩沖高速緩存中的域。如果cmd==READ,就是寫數據的位置;如果cmd==WRITE,就是讀數<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>緩沖高速緩存中的域。如果cmd==READ,就是寫數據的位置;如果cmd==WRITE,就是讀數<BR>據的位置。<BR>&nbsp;<BR>struct&nbsp;buffer_head&nbsp;*bh<BR>&nbsp;<BR>這個結構描述了這個請求列表中的第一個緩沖區。我們將在“集簇請求”中用到這個域<BR>。<BR>&nbsp;<BR>在這個結構中還有其它的一些域,但它們基本上是核心內部使用的,驅動程序并不期望<BR>使用它們。<BR>&nbsp;<BR>sbull中可工作的請求函數的實現如下所示。在下面的代碼中sbull-_devices與scull_de<BR>vice類似。我們在第三章字符設備驅動程序的“打開方法”中介紹過scull_devices。<BR>&nbsp;<BR>(代碼245)<BR>&nbsp;<BR>由于sbull只是個RAM盤,所以它的“數據傳送”簡化為一個memcpy調用。這個函數唯一<BR>“奇怪”的特征是條件語句中限制只能報告最多5個錯誤。這樣做的目的是為了防止系統<BR>日志被太多的信息搞亂,因為end-_request(0)在請求失敗時已打印了“I/O&nbsp;error”的<BR>消息。靜態計數器是限制消息報告的標準做法,在核心中被多次用到。<BR>&nbsp;<BR>集簇請求<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>上面請求函數中每次循環迭代都傳送幾個扇區——按照數據的使用,一般情況下,相當<BR>于一個塊的“數據”量。例如,交換一次執行PAGE_SIZE大小的數據,而在ext2文件系統<BR>中就是傳送1KB的塊。<BR>&nbsp;<BR>盡管在I/O中最方便的數據大小是一個塊,但如果把相鄰塊的讀或寫集簇起來,你會獲得<BR>很高的性能改善。在這個意義上,“相鄰”指的是在硬盤上塊的位置,而“連續”則指<BR>連續的內存區域。<BR>&nbsp;<BR>將相鄰塊集簇有兩個好處。首先,集簇加速了傳送(例如,軟盤驅動程序將相鄰的塊組<BR>合在一起,一次傳送一個磁道的數據)。另外,它還能通過避免分配冗余的request結構<BR>來節省核心中的內存。<BR>&nbsp;<BR>如果你愿意,也可以完全忽略集簇。上面給出的框架請求函數在沒有集簇的情況下可以<BR>完全正確地工作。不過,如果你想利用集簇,你需要更加仔細地研究struct_request的<BR>內部。<BR>&nbsp;<BR>不幸的是,我所知道的所有的核心(至少到2.1.51)都不能為自定義驅動程序進行集簇<BR>,而只對象SCSI和IDE這類內部驅動程序使用。如果你對核心的內部不感興趣,你可以跳<BR>過本節的其余部分。不過,集簇將來還可能在模塊中實現,它是通過減少相鄰扇區的請<BR>求延遲來提高數據傳送性能的一個有趣的途徑。<BR>&nbsp;<BR>在我描述驅動程序如何利用集簇請求之前,讓我們先來看看當一個請求被排隊時發生了<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>在我描述驅動程序如何利用集簇請求之前,讓我們先來看看當一個請求被排隊時發生了<BR>什么。<BR>&nbsp;<BR>當核心請求數據塊傳送時,它掃描目標設備的活動請求鏈表。當一個新塊在盤上與一個<BR>已經被請求的塊相鄰時,它就被集簇到第一個塊上。當前已存在的請求便被擴大了而不<BR>是增加一個新請求。<BR>&nbsp;<BR>不幸的是,磁盤上相鄰的兩個數據緩沖區在內存中并不一定相鄰。這個發現,外加上需<BR>要有效地管理緩沖高速緩存,導致創建一個buffer_head結構。一個buffer_head和一個<BR>數據緩沖相關聯。<BR>&nbsp;<BR>因此,一個“集簇”的請求,就是一個指向buffer_head的結構鏈表的request_struct結<BR>構。end_request函數負責這個問題,這就是為什么前面給出的請求函數可以獨立于集簇<BR>而工作。換句話說,end_request要么清除當前請求并準備為下一個服務,要么準備處理<BR>同一個請求中的下一個緩沖區。因此,集簇對不關心它的設備驅動程序是透明的,上面<BR>的sbull函數就是一個例子。<BR>&nbsp;<BR>一個驅動程序可能希望通過在它的request_fn函數中每次循環時處理整個緩沖區頭鏈表<BR>的辦法來從集簇中獲益。為了做到這一點,驅動程序應該指向CURRENT-&gt;current_nr_sec<BR>tors(這個域我在上面的sbull_request中已經用過)和CURRENT-&gt;nr_sectors,它包含<BR>了集簇在“當前”buffer_heads列表中的相鄰扇區的數目。<BR>&nbsp;<BR>當前緩沖區頭是CURRENT-&gt;bh,而數據塊是CURRENT-&gt;bh-&gt;b_data。后一個指針為了象sbu<BR></P></FONT><FONT 

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产欧美日韩在线| 国产成人日日夜夜| 成人在线视频首页| 在线播放91灌醉迷j高跟美女 | 欧美日本免费一区二区三区| 国产欧美视频一区二区三区| 日本亚洲三级在线| 在线亚洲一区二区| 国产欧美一区二区在线| 青娱乐精品视频| 在线观看91视频| 国产精品拍天天在线| 久久er99精品| 日韩欧美不卡一区| 午夜精品久久久久久久99樱桃| 9l国产精品久久久久麻豆| 久久综合久久综合久久综合| 麻豆精品一区二区| 欧美一区二区精美| 蜜桃av一区二区在线观看| 欧美日韩成人综合在线一区二区| 中文字幕在线一区| 成人午夜av影视| 国产欧美精品一区aⅴ影院| 国模娜娜一区二区三区| 日韩欧美一二区| 美女精品一区二区| 日韩小视频在线观看专区| 五月天精品一区二区三区| 欧美日韩在线一区二区| 亚洲一二三四区| 欧美性做爰猛烈叫床潮| 亚洲高清免费视频| 在线播放日韩导航| 看片网站欧美日韩| 久久夜色精品国产噜噜av| 国产精品538一区二区在线| 久久久精品日韩欧美| 高清成人免费视频| 亚洲人成精品久久久久| 欧美怡红院视频| 日日欢夜夜爽一区| 精品欧美久久久| 国产成人99久久亚洲综合精品| 欧美激情一区二区三区四区| 9人人澡人人爽人人精品| 亚洲制服丝袜av| 欧美一区二区私人影院日本| 麻豆91在线观看| 国产精品污网站| 色欧美乱欧美15图片| 日韩av中文字幕一区二区| 精品福利二区三区| 99在线视频精品| 亚洲福中文字幕伊人影院| 日韩精品一区二区三区在线观看| 国产制服丝袜一区| 日韩理论片一区二区| 欧美日韩一级视频| 国产乱一区二区| 一区二区三区日韩欧美精品| 欧美一区二区大片| 成人av在线看| 日韩av中文在线观看| 欧美极品另类videosde| 欧美日韩一级片网站| 国产精品亚洲第一| 亚洲一区二区三区四区五区中文 | 色婷婷综合久久久久中文| 日韩和欧美一区二区三区| 久久久综合网站| 欧美性三三影院| 成人一级视频在线观看| 五月婷婷久久综合| 国产精品美女久久久久久久| 在线综合视频播放| 成人av免费在线播放| 日韩国产在线观看| 亚洲精选视频在线| 久久免费看少妇高潮| 欧美视频一区二区三区| 国产精品自在在线| 丝袜a∨在线一区二区三区不卡| 亚洲国产高清在线| 精品国产91洋老外米糕| 制服.丝袜.亚洲.另类.中文| 91在线视频在线| 丁香婷婷综合激情五月色| 日韩高清不卡一区二区三区| 亚洲少妇屁股交4| 久久久亚洲精品石原莉奈| 欧美一级在线视频| 欧美日韩在线一区二区| 一本久道中文字幕精品亚洲嫩| 国内精品久久久久影院一蜜桃| 午夜国产不卡在线观看视频| 国产精品电影一区二区三区| 欧美国产日韩一二三区| 久久久99精品免费观看不卡| 日韩欧美一级片| 91精品国产全国免费观看| 欧美日韩一区二区三区四区| 91亚洲国产成人精品一区二区三| 国产成人欧美日韩在线电影 | 亚洲一区二区三区国产| 综合激情成人伊人| 中文一区在线播放| 国产精品免费视频网站| 国产蜜臀av在线一区二区三区| 亚洲精品在线免费观看视频| 日韩你懂的电影在线观看| 91精品国产福利| 日韩欧美亚洲另类制服综合在线| 91麻豆精品国产91久久久使用方法 | 免费成人你懂的| 久久精品国产亚洲高清剧情介绍| 水野朝阳av一区二区三区| 日韩精品91亚洲二区在线观看| 亚洲成人午夜电影| 青青草原综合久久大伊人精品优势| 亚洲永久精品大片| 五月天丁香久久| 美女精品自拍一二三四| 精品一区二区三区影院在线午夜| 蜜桃视频一区二区三区 | 色哟哟一区二区在线观看 | 国产一区二区三区日韩| 丰满亚洲少妇av| 99re在线精品| 欧美日韩免费观看一区三区| 7878成人国产在线观看| 久久午夜羞羞影院免费观看| 国产亚洲女人久久久久毛片| 国产精品进线69影院| 亚洲免费色视频| 视频一区中文字幕国产| 久草精品在线观看| 99这里只有精品| 在线电影一区二区三区| 久久伊99综合婷婷久久伊| 国产精品电影一区二区| 偷拍一区二区三区四区| 国产精品91一区二区| 波波电影院一区二区三区| 欧美三电影在线| 日韩精品中文字幕一区| 最新久久zyz资源站| 日韩成人一级片| av成人动漫在线观看| 欧美精品在线一区二区| 日本一区二区三区四区在线视频| 亚洲免费视频成人| 黑人巨大精品欧美黑白配亚洲| 91小视频在线观看| 欧美成人一区二区三区片免费| 国产精品久久久久一区 | 亚洲午夜精品久久久久久久久| 蜜桃一区二区三区在线观看| 99视频精品在线| 欧美精品一区二区三区在线播放| 亚洲日本中文字幕区| 久久99国产精品免费| 色综合咪咪久久| 26uuu国产电影一区二区| 亚洲一区二区视频在线| 国产一区二区三区| 欧美老女人在线| 亚洲欧洲日韩女同| 极品瑜伽女神91| 欧美精品在线视频| 亚洲六月丁香色婷婷综合久久 | 97精品久久久午夜一区二区三区| 日韩亚洲欧美在线观看| 一区二区三区**美女毛片| 国产精品白丝av| 日韩视频在线永久播放| 亚洲国产日韩一级| 不卡视频一二三| 国产欧美精品一区二区色综合朱莉| 婷婷中文字幕综合| 欧美综合一区二区| 亚洲欧美在线另类| 成人黄色在线视频| 久久精子c满五个校花| 极品瑜伽女神91| 欧美电影免费观看高清完整版| 亚洲成a人v欧美综合天堂| 92国产精品观看| 亚洲乱码国产乱码精品精98午夜 | 精品美女在线播放| 美女脱光内衣内裤视频久久网站 | 黄色日韩网站视频| 精品奇米国产一区二区三区| 日韩成人dvd| 日韩三级在线观看| 久久精品国产99久久6| 日韩精品综合一本久道在线视频| 日本欧美在线看| 91精品国产日韩91久久久久久| 日韩av中文字幕一区二区|