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

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

?? (ldd) ch05-字符設備驅動程序的擴展操作.htm

?? Linux設備驅動程序用于開發LINUX
?? HTM
?? 第 1 頁 / 共 4 頁
字號:
      color=#ffffff size=3>
      <P>“通過打印控制”的缺點是,它給設備增加了策略限制;例如,只有你確認控制序列不<BR>會出現在正常寫到設備的數據中時,這項技術才是可用的。對于終端來說,這只能說是<BR>部分正確。盡管文本顯示只意味著顯示ASCII字符,但有時控制字符也會出現在正在打印<BR>的數據中,因此會影響控制臺的配置。例如,當你對二進制文件進行grep時可能會發生<BR>這樣的情況;分解出的字符行可能什么都包含,最后經常會造成控制臺的字體錯誤*。<BR>&nbsp;<BR>寫控制特別適合這樣的設備,不傳輸數據,僅相應命令,如機器人設備。<BR>&nbsp;<BR>例如,我所寫的驅動程序之一是控制一個在兩個軸上的攝像頭的移動。在這個驅動程序<BR>中,“設備”是一對舊的步進馬達,它既不能讀也不能寫。向步進馬達“發送數據流”<BR>多少沒有多大意義。在這種情況下,驅動程序將所寫的數據解釋為ASCII命令,并將請求<BR>轉換為脈沖,實現對步進馬達的控制。命令可以是任何象“向左移動14步”,“達到位<BR>置100,43”或“降低默認速度”之類的字串。驅動程序僅將/dev中的設備節點當作為應<BR>用程序設立的命令通道。對該設備直接控制的優點是,你可以使用cat來移動攝像頭,而<BR>無需寫并編譯發出ioctl調用的特殊代碼。<BR>&nbsp;<BR>當編寫“面向命令的”驅動程序時,沒有理由要實現ioctl方法。為解釋器多實現一條命<BR>令對于實現和使用來說,都更容易。<BR>&nbsp;<BR>好奇的讀者可以看看由O’Reilly&nbsp;FTP站點提供的源碼stepper目錄中的stepper驅動程序<BR>;由于我認為代碼沒有太大的意義(而且質量也不是太高),這里沒有包含它。<BR>&nbsp;<BR>阻塞型I/O<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>阻塞型I/O<BR>read的一個問題是,當尚未有數據可讀,而又沒有到文件尾時如何處理。<BR>&nbsp;<BR>默認的回答是,“我們必須睡眠等待數據。”本節將介紹進程如何睡眠,如何喚醒,以<BR>及一個應用程序如何在不阻塞read調用的情況下,查看是否有數據。對于寫來說也可以<BR>適用同樣的方法。<BR>&nbsp;<BR>通常,在我向你介紹真實的代碼前,我將解釋若干概念。<BR>&nbsp;<BR>睡眠和喚醒<BR>當進程等待事件(可以是輸入數據,子進程的終止或是其他什么)時,它需要進入睡眠<BR>狀態以便其他進程可以使用計算資源。你可以調用如下函數之一讓進程進入睡眠狀態:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>然后用如下函數之一喚醒進程:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>在前面的函數中,wait_queue指針的指針用來代表事件;我們將在“等待隊列”一節中<BR>詳細討論這個數據結構。從現在開始,喚醒進程需要使用進程睡眠時使用的同一個隊列<BR>。因此,你需要為每一個可能阻塞進程的事件對應一個等待隊列。如果你管理4個設備,<BR>你需要為阻塞讀預備4個等待隊列,為阻塞寫再預備4個。存放這些隊列的最佳位置是與<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>你需要為阻塞讀預備4個等待隊列,為阻塞寫再預備4個。存放這些隊列的最佳位置是與<BR>每個設備相關的硬件數據結構(在我們的例子中就是Scull_Dev)。<BR>&nbsp;<BR>但“可中斷”調用和普通調用有什么區別呢?<BR>&nbsp;<BR>sleep_on不能信號取消,但interruptible_sleep_on可以。其實,僅在內核的臨界區才<BR>調用sleep_on;例如,當等待從磁盤上讀取交換頁面時。沒有這些頁面進程就無法繼續<BR>運行,用信號打斷這個操作是沒有任何意義的。然而,在所謂“長系統調用”,如read<BR>,中要使用interruptible_sleep_on。當進程正等待鍵盤輸入時,用一個信號將進程殺<BR>死是很有意義的。<BR>&nbsp;<BR>類似地,wake_up喚醒睡在隊列上的任何一個進程,而wake_up_interruptible僅喚醒可<BR>中斷進程。<BR>&nbsp;<BR>做為一個驅動程序編寫人員,由于進程僅在read或write期間才睡眠在驅動程序代碼上,<BR>你應該調用interruptible_sleep_on和wake_up_interruptible。不過,事實上由于沒有<BR>“不可中斷”的進程在你的隊列上睡眠,你也可以調用wake_up。但是,出于源代碼一致<BR>性的考慮,最好不這樣做。(此外,wake_up比它的搭檔來說要稍微慢一點。)<BR>&nbsp;<BR>編寫可重入的代碼<BR>當進程睡眠后,驅動程序仍然活著,而且可以由另一個進程調用。讓我們一控制臺驅動<BR>程序為例。當一個應用在tty1上等待鍵盤輸入,用戶切換到tty2上并派生了一個新的外<BR>殼。現在,兩個外殼都在控制臺驅動程序中等待鍵盤輸入,但它們睡在不同的隊列上:<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>殼。現在,兩個外殼都在控制臺驅動程序中等待鍵盤輸入,但它們睡在不同的隊列上:<BR>一個睡在與tty1相關的隊列上,一個睡在與tty2相關的隊列上。每個進程都阻塞在inter<BR>ruptible_sleep_on函數中,但驅動程序讓可以繼續接收和響應其他tty的請求。<BR>&nbsp;<BR>可以通過編寫“可重入代碼”輕松地處理這種情況。可重入代碼是不在全局變量中保留<BR>狀態信息的代碼,因此能夠管理交織在一起的調用,而不會將它們混淆起來。如果所有<BR>的狀態信息都與進程有關,就不會發生相互干擾。<BR>&nbsp;<BR>如果需要狀態信息,既可以在驅動程序函數的局部變量中保存(每個進程都有不同的堆<BR>棧來保存局部變量),也可以保存在訪問文件用的filp中的private_data中。由于同一<BR>個filp可能在兩個進程間共享(通常是父子進程),最好使用局部變量*。<BR>&nbsp;<BR>如果你需要保存大規模的狀態信息,你可以將指針保存在局部變量中,并用kmalloc獲取<BR>實際存儲空間。此時,你千萬別忘了kfree這些數據,因為當你在內核空間工作時,沒有<BR>“在進程終止時釋放所有資源”的說法。<BR>&nbsp;<BR>你需要將所有調用了sleep_on(或是schedule)的函數寫成可重入的,并且包括所有在<BR>這個函數調用軌跡中的所有函數。如果sample_read調用了sample_getdata,后者可能會<BR>阻塞,由于調用它們的進程睡眠后無法阻止另一個進程調用這些函數,sample_read和sa<BR>mple_gendata都必須是可重入的。此外,任何在用戶空間和內核空間復制數據的函數也<BR>必須是可重入的,這是因為訪問用戶空間可能會產生頁面失效,當內核處理失效頁面時<BR>,進程可以會進入睡眠狀態。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>等待隊列<BR>我聽見你在問的下一個問題是,“我到底如何使用等待隊列呢?”<BR>&nbsp;<BR>等待隊列很容易使用,盡管它的設計很是微妙,但你不需要直到它的內部細節。處理等<BR>待隊列的最佳方式就是依照如下操作:<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;聲明一個struct&nbsp;wait_queue&nbsp;*變量。你需要為每一個可以讓進程睡眠的事件<BR>預備這樣一個變量。這就是我建議你放在描述硬件特性數據結構中的數據項。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;將該變量的指針做為參數傳遞給不同的sleep_on和wake_up函數。<BR>&nbsp;<BR>這相當容易。例如,讓我們想象一下,當進程讀你的設備時,你要讓這個進程睡眠,然<BR>后在某人向設備寫數據后喚醒這個進程。下面的代碼就可以完成這些工作:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>該設備的這段代碼就是例子程序中的sleepy,象往常一樣,可以用cat或輸入/輸出重定<BR>向等方法測試它。<BR>&nbsp;<BR>上面列出的兩個操作是你唯一操作在等待隊列上的兩個操作。不過,我知道某些讀者對<BR>它的內部結構感興趣,但通過源碼掌握它的內部結構很困難。如果你不對更多的細節感<BR>興趣,你可以跳過下一節,你不會損失什么的。注意,我談論的是“當前”實現(版本2<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>興趣,你可以跳過下一節,你不會損失什么的。注意,我談論的是“當前”實現(版本2<BR>..0.x),但沒有什么規定限制內核開發人員必須依照那樣的實現。如果出現了更好的實<BR>現,內核很容易就會使用新的,由于驅動程序編寫人員只能通過那兩個合法操作使用等<BR>待隊列,對他們來說沒有什么壞的影響。<BR>&nbsp;<BR>當前struct&nbsp;wait_queue額實現使用了兩個字段:一個指向struct&nbsp;task_struct結構(等<BR>待進程)的指針,和一個指向struct&nbsp;wait_queue(鏈表中的下一個結構)的指針。等待<BR>隊列是循環鏈表,最后一個結構指向第一個結構。<BR>&nbsp;<BR>該設計的引入注目的特點是,驅動程序編寫人員從來不聲明或使用這個結構;他們僅僅<BR>傳遞它的指針或指針的指針。實際的結構是存在的,但只在一個地方:在__sleep_on函<BR>數的局部變量中,上面介紹的兩個sleep_on函數最終會調用這個函數。<BR>&nbsp;<BR>這看上去有點奇怪,不過這是一個非常明智的選擇,因為無需處理這種結構的分配和釋<BR>放。進程每次睡在某個隊列上,描述其睡眠的數據結構駐留在進程對應的不對換的堆棧<BR>頁中。<BR>&nbsp;<BR>當進程加入或從隊列中刪除時,實際的操作如圖5-1所示。<BR>&nbsp;<BR>(圖5-1&nbsp;等待隊列的工作示意)<BR>&nbsp;<BR>阻塞型和非阻塞型操作<BR>在分析功能完整的read和write方法前,我們還需要看看另外一個問題,這就是filp-&gt;f_<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>在分析功能完整的read和write方法前,我們還需要看看另外一個問題,這就是filp-&gt;f_<BR>flags中的O_NONBLOCK標志。這個標志定義在&lt;linux/fcntl.h&gt;中,在最近的內核中,這<BR>個頭文件由&lt;linux/fs.h&gt;自動包含了。如果你在內核1.2中編譯你的模塊,你需要手動包<BR>含fcntl.h。<BR>&nbsp;<BR>這個標志的名字取自“打開-非阻塞”,因為這個標志可以在打開時指定(而且,最初只<BR>能在打開時指定)。由于進程在等待數據時的正常行為就是睡眠,這個標志默認情況下<BR>是復位的。在阻塞型操作的情況下,應該實現下列操作:<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果進程調用read,但(尚)沒有數據,進程必須阻塞。當數據到達時,進程<BR>被喚醒,并將數據返回給調用者,即便少于方法的count參數中所請求的數據量,也是如<BR>此。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果進程調用了write,緩沖區又沒有空間,進程也必須阻塞,而且它必須使<BR>用與用來實現讀的等待隊列不同的等待隊列。當數據寫進設備后,輸出緩沖區中空出部<BR>分空間,喚醒進程,write調用成功完成,如果緩沖區中沒有請求中count個字節,則進<BR>程可能只是完成了部分寫。<BR>&nbsp;<BR>前面的列表的兩個語句都假設,有一個輸入和輸出緩沖區,而且每個設備驅動程序都有<BR>一個。輸入緩沖區需要用來在數據達到而又沒有人讀時避免丟失數據,輸出緩沖區用來<BR>盡可能增強計算機的性能,盡管這樣做不是嚴格必須的。由于如果系統調用不接收數據<BR>的話,數據仍然保存在用戶空間的緩沖區中,write中可以丟失數據。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>在驅動程序中實現輸出緩沖區可以獲得一定的性能收益,這主要是通過較少了用戶級/內<BR>核級轉換和上下文切換的數目達到的。如果沒有輸出緩沖區(假設是一個慢設備),每<BR>次系統調用只接收一個或很少幾個字節,并且當進程在write中睡眠時,另一進程就會運<BR>行(有一次上下文切換)。當第一個進程被喚醒后,它恢復運行(又一次上下文切換)<BR>,write返回(內核/用戶轉換),進程還要繼續調用系統調用寫更多的數據(內核/用戶<BR>轉換);然后調用再次被阻塞,再次進行整個循環。如果輸出緩沖區足夠大,write首次<BR>操作時就成功了;數據在中斷時被推送給設備,而不必將控制返回用戶空間。適合于設<BR>備的輸出緩沖區的尺寸顯然是和設備相關的。<BR>&nbsp;<BR>我們沒有在scull中使用輸入緩沖區,這是因為當調用read時,數據已經就緒了。類似地<BR>,也沒有使用輸出緩沖區,數據簡單地復制到設備對應的內存區中。我們將在第9章“中<BR>斷處理”的“中斷驅動的I/O”一節中介紹緩沖區的使用。<BR>&nbsp;<BR>如果設置了O_NONBLOCK標志,read和write的行為是不同的。此時,如果進程在沒有數據<BR>就緒時調用了read,或者在緩沖區沒有空間時調用了write,系統簡單地返回-EAGAIN。<BR>&nbsp;<BR>如你所料,非阻塞型操作立即返回,允許應用查詢數據。當使用stdio函數處理非阻塞型<BR>文件時,由于你很容易誤將非阻塞返回認做是EOF,應用程序應該非常小心。你必須始終<BR>檢查errno。<BR>&nbsp;<BR>你也許可以從它的名字猜到,O_NONBLOCK在open方法也可有作用。當open調用可能會阻<BR>塞很長時間時,就需要O_NONBLOCK了;例如,當打開一個FIFO文件而又(尚)無寫者時<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>塞很長時間時,就需要O_NONBLOCK了;例如,當打開一個FIFO文件而又(尚)無寫者時<BR>,或是訪問一個被鎖住的磁盤文件時。通常,打開設備成功或失敗,無需等待外部事件<BR>。但是,有時打開設備需要需要很長時間的初始化,你可以選擇打開O_NONBLOCK,如果<BR>設置了標志,在設備開始初始化后,會立即返回一個-EAGAIN(再試一次)。你還可以為<BR>支持訪問策略選擇實現阻塞型open,方式與文件鎖類似。我們稍后將在“替代EBUSY的阻<BR>塞型打開”一節中看到這樣一種實現。<BR>&nbsp;<BR>只有read,write和open文件操作受非阻塞標志的影響。<BR>&nbsp;<BR>樣例實現:scullpipe<BR>/dev/scullpipe設備(默認有4個設備)是scull模塊的一部分,用來展示如何實現阻塞<BR>型I/O。<BR>&nbsp;<BR>在驅動程序內部,阻塞在read調用的進程在數據達到時被喚醒;通常會發出一個中斷來<BR>通知這樣一種事件,驅動程序在處理中斷時喚醒進程。由于你應該無需任何特殊硬件―<BR>―沒有任何中斷處理函數,就可以在任何計算機上運行scull,scull的目標與傳統驅動<BR>程序完全不同。我選擇的方法是,利用另一個進程產生數據,喚醒讀進程;類似地,用<BR>讀進程喚醒寫者。這種實現非常類似與一個FIFO(或“命名管道”)文件系統節點的實<BR>現,設備名就出自此。<BR>&nbsp;<BR>設備驅動程序使用一個包含兩個等待隊列和一個緩沖區的設備結構。緩沖區的大小在通<BR>常情況下是可以配置的(編譯時,加載時和運行時)。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>(代碼)<BR>&nbsp;<BR>read實現管理阻塞型和非阻塞型數據,如下所示:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>如你所見,我在代碼中留下了PDEBUG語句。當你編譯驅動程序時,你可以打開消息,這<BR>樣就可以更容易地看到不同進程間的交互了。<BR>&nbsp;<BR>跟在interruptible_sleep_on后的if語句處理信號處理。這條語句保證對信號恰當和預<BR>定的處理過程,它會讓內核完成系統調用重啟或返回-EINTR(內核在內部處理-ERESTART<BR>SYS,最終返回到用戶空間的是-EINTR)。我不想讓內核對阻塞信號完成這樣的處理,主<BR>要時我想忽略這些信號。否則,我們可以返回-ERESTARTSYS錯誤給內核,讓它完成它的<BR>處理工作。我們將在所有的read和write實現中使用一樣的語句進行信號處理。<BR>&nbsp;<BR>write的實現與read非常相似。它唯一的“特殊”功能時,它從不完全填充緩沖區,總時<BR>留下至少一個字節的空洞。因此,當緩沖區空的時候,wp和rp時相等的;當存在數據時<BR>,它們是不等的。<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>正如我所構想的,設備沒有實現阻塞型open,這要比實際的FIFO要簡單得多。如果你想<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>正如我所構想的,設備沒有實現阻塞型open,這要比實際的FIFO要簡單得多。如果你想<BR>要看看實際的代碼,你可以在內核源碼的fs/pipe.c中找到那些代碼。<BR>&nbsp;<BR>要測試scullpipe設備的阻塞型操作,你可以在其上運行一些應用,象往常一樣,可以使<BR>用輸入/輸出重定義等方法。由于普通程序不執行非阻塞型操作,測試非阻塞活動要麻煩<BR>些。misc-progs源碼目錄中包含了一個很簡單的程序,稱為nbtest,用它來測試非阻塞<BR>型操作,該程序羅列如下。它所做的就是使用非阻塞型I/O復制它的輸入和輸出,并在期<BR>間稍做延遲。延遲時間可以通過命令行傳遞,默認情況下時1秒鐘。<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>Select<BR>在使用非阻塞型I/O時,應用程序經常要利用select系統調用,當涉及設備文件時,它依<BR>賴于一個設備方法。這個系統調用還用來實現不同源輸入的多路復用。在下面的討論中<BR>,我假設你知道在用戶空間中select的語義的用法。注意,內核2.1.23引入了poll系統<BR>調用,因此為了支持這兩個系統調用,它改變驅動程序方法的工作方式。<BR>&nbsp;<BR>為了保存所有正在等待文件(或設備)的信息,Linux&nbsp;2.0的select系統調用的實現使用<BR>了select_table結構。再次提醒你,你無需了解它的內部結構(但不管怎樣,我們一會<BR>會稍做介紹),而且只允許調用操作該結構的函數。<BR>&nbsp;<BR>當select方法發現無需阻塞時,它返回1;當進程應該等待,它應該“幾乎”進入睡眠狀<BR>態。在這種情況下,要在select_table結構中加入等待隊列,并且返回0。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>態。在這種情況下,要在select_table結構中加入等待隊列,并且返回0。<BR>&nbsp;<BR>僅當選擇的文件中沒有一個可以接收或返回數據時,進程才真正進入睡眠狀態。這一過<BR>程發生在fs/select.c的sys_select中。<BR>&nbsp;<BR>寫select操作的代碼要比介紹它要容易得多,現在就可以scull中時如何實現的:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>這里沒有代碼處理“第3種形式的選擇”,選擇異常。這種形式的選擇時通過mode&nbsp;==<BR>SEL_EX標別的,但大多數時候你都將其編寫為默認情況,在其他選擇均失敗時執行。異<BR>常事件的含義與設備有關,所以你可以選擇是否在你自己的驅動程序中實現它們。這種<BR>功能將只會為專為你的驅動程序設計的程序使用,但那并不它的初衷。在這方面,它與<BR>依賴于設備的ioctl調用很相似。在實際使用中,select中異常條件的主要用途是,通知<BR>網絡連接上帶外(加急)數據的達到,但它還用在終端層以及管道/FIFO實現中(你可以<BR>查看fs/pipe.c中的SEL_EX)。不過要注意,其他Unix系統的管道和FIFO沒有實現異常條<BR>件。<BR>&nbsp;<BR>這里給出的select代碼缺少對文件尾的支持。當read調用達到文件尾時,它應該返回0,<BR>select必須通過通告設備可讀來支持這種行為,這樣應用程序就不會永遠等待調用read<BR>了。例如,在實際的FIFO中,當所有的寫者都關閉了文件時,讀者會看到文件尾,而在s<BR>cullpipe中,讀者永遠也看不到文件尾。設計這種不同行為的原因時,一般將FIFO當做<BR>兩個進程間的通信通道,而scullpipe是一個只要至少有一個讀者,所有人就都可以輸入<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>兩個進程間的通信通道,而scullpipe是一個只要至少有一個讀者,所有人就都可以輸入<BR>數據的垃圾筒。此外,也沒有必要重新實現內核中已經有了的設備。<BR>&nbsp;<BR>象FIFO那樣實現文件尾意味著要在read和讀select中檢查dev-&gt;nwriters,并做相應處理<BR>。不過很遺憾,如果讀者在寫者前打開設備,它馬上就看到文件尾了,沒有機會等待數<BR>據到達。最好的解決這個問題的方法是,實現阻塞型open,這個任務做為練習留給讀者<BR>。<BR>&nbsp;<BR>與read和write的交互<BR>select調用的目的是事先判斷是否有I/O操作會阻塞。從這個方面說,它時對read和writ<BR>e的補充。由于select可以讓驅動程序同時等待多個數據流(但這與這里的情況無關),<BR>select在這方面也時很有用途的。<BR>&nbsp;<BR>為了讓應用正確工作,正確實現這3個調用時非常重要的。盡管下面的規則已經多多少少<BR>談過了一些,我還要在這里再總結一下。<BR>&nbsp;<BR>從設備讀取數據<BR>如果在輸入緩沖區中有數據,即便比所請求的數據少,而且驅動程序可以保證剩下的數<BR>據會馬上達到,read調用應該不經過任何可以察覺的延遲立即返回。如果你至少可以返<BR>回1個字節,而且很方便的話,你總可以返回比請求少的數據(我們在scull就是這樣做<BR>的)。當前內核中總線鼠標的實現在這方面就時錯的,某些程序(如dd)無法正確讀取<BR>這些設備。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>如果輸入緩沖區中沒有數據,在至少有一個字節可讀前read必須阻塞,除非設置了O_NON<BR>BLOCK。非阻塞型read立即返回-EAGAIN(盡管在這種情況下某些舊的System&nbsp;V會返回0)<BR>。在至少有一個字節可讀前,select必須報告設備不可讀。只要有數據可讀,我們就使<BR>用上一條規則。<BR>&nbsp;<BR>如果我們到了文件尾,,無論是否有O_NONBLOCK,read都應該立即返回0。select應該報<BR>告說文件可讀。<BR>&nbsp;<BR>向設備寫數據<BR>如果輸出緩沖區有空間,write應該不做任何延遲返回。它可以接收少于請求數目的數據<BR>,但是它須接收至少一個字節。在這種情況下,select應該報告設備可寫。<BR>&nbsp;<BR>如果輸出緩沖區是滿的,在空間釋放前write一直阻塞,除非設置了O_NONBLOCK標志。非<BR>阻塞型write立即返回,返回值為-EAGAIN(或者在某些條件為0,如前面舊版本的System<BR>&nbsp;V所說)。select應該報告文件不可寫。但另一方面,如果設備不能接收任何數據,無<BR>論是否設置了O_NONBLOCK,write都返回-ENOSPC(“設備無可用空間”)。<BR>&nbsp;<BR>如果使用設備的程序需要確保等候在輸出隊列中的數據真的完成了傳送,驅動程序必須<BR>提供一個fsync方法。例如,可移動設備使用提供fsync入口點。千萬不要在調用返回前<BR>讓write調用等待數據傳送結束。這是因為,需要應用程序都可用select檢查設備是否時<BR>可以寫的。如果設備報告可以寫,write調用應該保持一致,不能阻塞。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>刷新待處理輸出<BR>我們已經看到write方法為什么不能滿足所有數據輸出的需求。通過同名系統調用調用的<BR>fsync函數彌補了這一空缺。<BR>&nbsp;<BR>如果某些應用需要確保數據傳送到設備上,設備就必須實現fsync方法。無論是否設置了<BR>O_NONBLOCK標志,fsync調用應該僅在設備已經完全刷新數據后才能返回,甚至花些時間<BR>也要如此。<BR>&nbsp;<BR>fsync方法沒有什么不尋常的功能。調用不是時間關鍵的,所以每個設備驅動程序都可以<BR>按照作者的風<BR>&nbsp;<BR>--<BR>&nbsp;<BR><FONT 
      color=#00ff00>※&nbsp;來源:.華南網木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;202.38.196.234]</FONT><BR>--<BR><FONT 
      color=#00ffff>※&nbsp;轉寄:.華南網木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#0000ff>※&nbsp;轉寄:.華南網木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#ffff00>※&nbsp;轉載:.南京大學小百合站&nbsp;bbs.nju.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>&nbsp;<BR>--<BR><FONT 
      color=#ff0000>※&nbsp;轉載:·飲水思源&nbsp;bbs.sjtu.edu.cn·[FROM:&nbsp;211.80.41.106]</FONT><BR></P></FONT>
      <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/6.htm"><FONT color=#ffffff 
      size=2>上一頁</FONT></A> | <A 
      href="http://211.71.69.201/joyfire/lsdp/8.htm"><FONT color=#ffffff 
      size=2>下一頁</FONT></A></P></SPAN></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>
  <TBODY>
  <TR>
    <TD colSpan=3 height=2>
      <TABLE cellSpacing=0 cellPadding=0 width="100%" bgColor=#666666 
        border=0><TBODY>
        <TR>
          <TD width="38%" height=4>

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲成人资源在线| 亚洲男女一区二区三区| 欧美日韩在线亚洲一区蜜芽| 波多野结衣的一区二区三区| 国产99精品国产| 99久久亚洲一区二区三区青草| 风间由美性色一区二区三区| 成人亚洲一区二区一| 成人免费视频播放| 国产福利一区二区三区视频| 不卡av免费在线观看| 91女神在线视频| 欧美色中文字幕| 欧美一二三四在线| 久久综合久久鬼色| 自拍偷拍亚洲综合| 亚洲夂夂婷婷色拍ww47| 美女任你摸久久 | 欧美日韩一区小说| 欧美一级日韩免费不卡| 欧美精品一区二区不卡| 亚洲国产精品国自产拍av| 亚洲日本韩国一区| 奇米影视在线99精品| 成人午夜视频网站| 欧美狂野另类xxxxoooo| 26uuu国产电影一区二区| 中文字幕一区二区三区在线不卡| 尤物在线观看一区| 狠狠色综合播放一区二区| av在线不卡电影| 欧美电影在线免费观看| 国产校园另类小说区| 亚洲国产成人av好男人在线观看| 久久国产人妖系列| 色婷婷综合视频在线观看| 欧美变态tickle挠乳网站| 亚洲蜜桃精久久久久久久| 麻豆成人久久精品二区三区小说| 成人一区二区三区在线观看| 9191成人精品久久| 亚洲欧美二区三区| 精品一区二区在线播放| 色av成人天堂桃色av| 26uuu另类欧美| 亚洲最大色网站| 成人黄色在线网站| 精品久久人人做人人爽| 亚洲国产精品视频| 成人午夜电影久久影院| 欧美大片日本大片免费观看| 一区二区高清免费观看影视大全| 国产在线一区观看| 日韩一区二区三区av| 亚洲一区二区三区影院| 波多野结衣中文一区| 亚洲精品一区二区在线观看| 午夜精品一区二区三区三上悠亚| 91视频.com| 国产精品久久久久久久久免费桃花 | 亚洲成va人在线观看| 99久久亚洲一区二区三区青草| 26uuu精品一区二区| 美女一区二区在线观看| 欧美日韩国产经典色站一区二区三区| 国产精品大尺度| 成人av动漫在线| 国产精品毛片久久久久久久| 国产成人av电影在线观看| 日韩欧美国产成人一区二区| 秋霞av亚洲一区二区三| 51精品国自产在线| 日产国产欧美视频一区精品| 欧美亚洲精品一区| 亚洲国产日韩av| 91麻豆精品国产| 亚洲午夜电影在线| 欧美精品xxxxbbbb| 麻豆精品视频在线观看视频| 欧美一区二区三区公司| 蜜桃一区二区三区四区| 精品国产乱码久久久久久蜜臀 | 亚洲国产成人av好男人在线观看| 色吊一区二区三区| 亚洲成人1区2区| 日韩一级在线观看| 国产乱子伦视频一区二区三区| 精品久久人人做人人爽| 国产成人综合在线| 亚洲猫色日本管| 欧美日韩国产bt| 国内精品国产三级国产a久久 | 一区2区3区在线看| 欧美日韩亚洲国产综合| 蜜桃精品视频在线| 国产精品女主播av| 91九色最新地址| 美女任你摸久久 | 91国偷自产一区二区开放时间 | 国产精品视频免费看| 色丁香久综合在线久综合在线观看| 亚洲一区二区在线免费看| 337p亚洲精品色噜噜狠狠| 精久久久久久久久久久| 欧美激情一区二区在线| 欧美综合一区二区三区| 九一久久久久久| 亚洲欧美视频在线观看视频| 欧美一区二区网站| av中文字幕在线不卡| 青青国产91久久久久久| 亚洲欧洲日韩在线| 欧美变态tickle挠乳网站| 91看片淫黄大片一级在线观看| 久久国产精品99精品国产| 亚洲激情欧美激情| 欧美巨大另类极品videosbest| 激情伊人五月天久久综合| 亚洲欧美国产高清| 在线看不卡av| 亚洲一区二区五区| 26uuu欧美| 国产精品视频在线看| 国产精品黄色在线观看| 国产精品三级在线观看| 国产精品高清亚洲| 国产精品人妖ts系列视频| 国产精品超碰97尤物18| 一区二区三区美女| 亚洲成av人片| 久久99国产精品免费网站| 国产一区二区三区久久久| 成人午夜免费视频| 欧美综合色免费| 欧美一区2区视频在线观看| 日韩亚洲欧美在线| 日本一区二区免费在线观看视频| 国产欧美日本一区视频| 一区二区三区在线观看网站| 日韩av在线免费观看不卡| 国产制服丝袜一区| 色狠狠av一区二区三区| 制服丝袜亚洲精品中文字幕| 久久精品这里都是精品| 亚洲免费观看高清| 蜜臀精品久久久久久蜜臀| 国产91在线看| 欧美精品一二三四| 日本一区二区视频在线| 亚洲国产cao| 国产成人免费视频一区| 91国偷自产一区二区三区观看 | 亚洲一二三四在线| 麻豆国产精品一区二区三区| 99久久婷婷国产综合精品电影 | 久久成人免费网| 91在线视频18| 日韩午夜激情av| 亚洲精品日产精品乱码不卡| 日韩av一区二区三区四区| 成人午夜激情在线| 日韩精品一区二区三区老鸭窝| 国产精品美女一区二区| 久久激情五月婷婷| 欧美视频一区二区三区在线观看| 久久久久久97三级| 午夜精品福利一区二区三区av| 国产成人免费在线视频| 欧美日本高清视频在线观看| 综合久久综合久久| 国产馆精品极品| 日韩视频一区在线观看| 亚洲精品中文在线| 成人亚洲一区二区一| 精品久久久久香蕉网| 丝袜美腿亚洲一区| 欧美在线观看一二区| 欧美国产精品一区二区| 国产美女在线观看一区| 日韩欧美一区电影| 日本美女一区二区| 欧美理论片在线| 伊人开心综合网| 91在线播放网址| 国产精品全国免费观看高清 | 97国产一区二区| 精品乱人伦小说| 麻豆精品国产传媒mv男同| 在线亚洲高清视频| **欧美大码日韩| www.欧美色图| 亚洲欧洲www| 成人动漫视频在线| 国产精品成人免费在线| 波多野结衣一区二区三区 | 国产清纯白嫩初高生在线观看91 | 蜜芽一区二区三区| 日韩一区二区三区精品视频| 日韩国产精品久久| 欧美久久久久久久久久|