A. 面試的時候被問到java Io 該怎麼回答
樓主可以這么回答IO就是In 和 Out的縮寫。。。。
B. java面試nio和io的區別
面向流與面向緩沖
Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩沖區的。 Java IO面向流意味著每次從流中讀一個或多個位元組,直至讀取所有位元組,它們沒有被緩存在任何地方。此外,它不能前後移動流中的數據。如果需要前後移動從流中讀取的數據,需要先將它緩存到一個緩沖區。 Java NIO的緩沖導向方法略有不同。數據讀取到一個它稍後處理的緩沖區,需要時可在緩沖區中前後移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區中包含所有您需要處理的數據。而且,需確保當更多的數據讀入緩沖區時,不要覆蓋緩沖區里尚未處理的數據。
阻塞與非阻塞IO
Java IO的各種流是阻塞的。這意味著,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。 Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什麼都不會獲取。而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閑時間用於在其它通道上執行IO操作,所以一個單獨的線程現在可以管理多個輸入和輸出通道(channel)。
選擇器(Selectors)
Java NIO的選擇器允許一個單獨的線程來監視多個輸入通道,你可以注冊多個通道使用一個選擇器,然後使用一個單獨的線程來「選擇」通道:這些通道里已經有可以處理的輸入,或者選擇已准備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。
NIO和IO如何影響應用程序的設計
無論您選擇IO或NIO工具箱,可能會影響您應用程序設計的以下幾個方面:
1.對NIO或IO類的API調用。
2.數據處理。
3.用來處理數據的線程數。
API調用
當然,使用NIO的API調用時看起來與使用IO時有所不同,但這並不意外,因為並不是僅從一個InputStream逐位元組讀取,而是數據必須先讀入緩沖區再處理。
數據處理
使用純粹的NIO設計相較IO設計,數據處理也受到影響。
C. java面試考IO的多嗎
IO文件流嗎 還好,一般般。會有一些文件讀寫之類的面試題,主要出現在筆試上。
D. Java實習生工作需要具備哪些能力
結合企業對求職者的技能要求就給大家簡單分析一下。
宏觀方面
1)要精通多門開源技術,研究過struts spring等的源碼;
2)具有豐富的項目經驗,從頭到尾跟過幾個大項目,從需求調研到上線交付維護階段;
3)有過分布式系統的架構和開發經驗,對於跨系統的結構優化、數據存儲的性能指標等有豐富經驗。
微觀方面
1)熟練的使用Java語言進行面向對象程序設計,有良好的編程習慣,熟悉常用的Java API,包括集合框架、多線程(並發編程)、I/O(NIO)、Socket、JDBC、XML、反射等;
2)熟悉基於JSP和Servlet的Java Web開發,對Servlet和JSP的工作原理和生命周期有深入了解,熟練的使用JSTL和EL編寫無腳本動態頁面;
3)熟練的使用HTML、CSS和JavaScript進行Web前端開發,熟悉jQuery和Bootstrap,對Ajax技術在Web項目中的應用有深入理解;
4)熟練的使用Hibernate、MyBatis等ORM框架,熟悉Hibernate和MyBatis的核心API,對Hibernate的關聯映射、繼承映射、組件映射、緩存機制、事務管理以及性能調優等有深入的理解。
E. java面試io流問的多嗎
看你面試哪種層次的公司了,一般公司就一些se基礎,偶爾涉及一些框架,
牛一點的問的就比較深了,主要看你簡歷上怎麼寫 的
F. 叫你如何通過硬體工程師面試
通過硬體工程師面試,遇到的常見的問題:
PCB的兩條走線過長平行走線會引起什麼後果?
從信號完整性方面來考慮,過長的走線耦合增強,串擾的本質在於耦合,所以過長平行走線會引起串擾,可能會引起誤碼操作。
常見的組合邏輯電路有哪些?
加法器,數據選擇器,數據輸出器,編碼器,解碼器,數值比較單元,算數邏輯單元。
存儲器有哪些構成?
存儲陣列,地址解碼器和輸出控制電路。
鎖相環電路的基本構成?
分頻器、鑒頻鑒相器、環路濾波器、壓控振盪器。
RS232和RS485的主要區別?
RS232是利用傳輸線與公共地之間的電壓差傳輸信號,RS485是利用傳輸線之間的電壓差作為傳輸信號,由於電壓差分對的存在,可以很好的抑制共模干擾,所以RS485傳輸更遠。
驅動蜂鳴器的三極體工作在哪個區,若是做反相器呢?
由於單片機等其他MCU IO輸出的電流比較小,大概在幾十個mA以下,所以為了驅動需要電流較大的器件,需要額外的器件。驅動蜂鳴器利用三極體,使其工作在放大區。利用三極體的飽和和截止特性,可以做反相器,作為開關使用。
四層板信號分布是怎麼樣的,才能使EMC降低?
對於常用的4層板信號分布是,信號層–地層(電源層)—電源層(地層)—信號層。這樣設置的原則是(1)電源層和地層相鄰,可以耦合電源的雜訊,降低因電源抖動對器件的影響。(2)頂層和底層都有相應的參考層,可以良好的達到信號阻抗要求。(3)因兩個信號層都有參考層,所以都有各自的參考迴流路徑,可以降低EMI。
分析競爭與冒險如何產生的以及如何避免?
信號經過邏輯門電路都需要要一定的時間,不同的傳輸路徑上門電路數量不一樣或者門電路數量一樣,但每個門電路的延遲時間不一樣,使得與穩態下得到的邏輯功能不一致,產生錯誤的輸出。到達的時間不一致稱為競爭,產生的毛刺稱為冒險。
解決辦法:1.增加選通電路;2.晶元外部添加電容;3.增加布爾式的消去項;
傳輸線幾個重要的經驗公式?
對於傳輸線上任何串聯連接都有電容參數,為了使其不產生對信號線變緩趨勢,需要滿足 C < 4 *RT。對於傳輸線上任何串聯連接都有電感參數,為了使其不產生尖峰信號,需要滿足 L < 0.2 * Z0 *RT。
AD電路中,濾波為什麼採用磁珠濾波,而不是電感?
良好的濾波電路對AD器件影響是較大,雜訊大,可能會引起誤碼操作。磁珠濾波是吸收雜訊,轉化成熱,電感濾波時反射雜訊,並沒有消除雜訊。
解釋一下電感,磁珠和電容濾波原理?
磁珠濾波是吸收雜訊磁珠的等效形式為電抗(電感) + 電阻,在低頻段,磁珠表現為感性,反射雜訊,在高頻段表現為阻性,吸收雜訊,並轉化成熱。所以選擇磁珠時需要考慮電路上的信號和雜訊所處的頻帶,盡量讓工作頻率高於磁珠的轉化頻率,處在阻性范圍。 對於磁珠的選擇需要考慮的方面:(1)考慮信號工作的頻帶范圍,好確定磁珠的選型,盡量讓其大於磁珠的轉換頻率;(2)直流電阻,選擇低Rdc,降低流過磁珠本身的損耗;(3)額定電流,選擇磁珠的額定電流盡量接近或者大於工作電流;(4)自諧振頻率,應選擇自諧振頻率較高的磁珠,因為工作頻率大於自諧振頻率時,會表現為電容特性,會迅速降低阻抗。
電感濾波是反射雜訊,首先說一下電感的作用(1)通直流隔交流;(2)濾波;(3)阻礙電流的變化,維持電流的穩定。因為電感本身也有一定的阻抗,所以在大電流流過時需要考慮電感上的壓降,還要注意組成的LC高通或者低通濾波器,不要使其諧振頻率工作在器件本身的工作頻帶范圍內,否則會引起諧振,紋波變大。選擇電感時,其諧振頻率要高於工作頻率,當低於諧振頻率時,電感值保持穩定,高於諧振頻率時,不過增加到一定程度後不再增加,頻率在增加電感表現為電容性,會隨頻率增高而迅速減小。
電容濾波是反射雜訊,電容的等效模型為電感+電容+電阻的串聯,在諧振頻率之前,電容表現為電容特性,隨著頻率增加,阻抗變小,但是隨著頻率超過工作頻率,會使得電容轉化為電感特性,隨著頻率的增加阻抗變大。電容的作用(1)通交流隔直流;(2)濾波,高頻雜訊的泄放通道;(3)續流池,維持電壓的穩定。電容有ESR和ESL特性,ESR表現為其內部有一定的電阻特性。ESL與電容的封裝尺寸有關,F = (ESL * C)^(-1/2)。對於ESL特性,所以在選擇電容濾波的時候,盡量不要選擇同一封裝不同容值,或者同一容值不同封裝,這對於濾波會有一定的作用,但是不明顯,濾波效果較好的是不同容值不同封裝類型,可以基本上濾波各個頻段的雜訊。
對於電容的選擇一般是 陶瓷電容 高頻,鉭電容一般是中頻,電解電容一般是低頻。容值越大的鉭電容其ESR值越小。
3W,20H什麼意思?
3W是相鄰走線中心距為標准線寬的3倍。H表示是電源層到底層的厚度,電源層相對於底層內縮20H,以吸收電源平面的輻射。
狀態機中的摩爾和米莉有什麼區別?
摩爾型狀態機只和狀態有關,米莉型不單單和當前狀態有關,還和輸入有關。
基爾霍夫電流定律和電壓定律?
在集總電路中,對於任一結點,所有流出結點的支路電流代數和恆等於零。
在集總電路中,對於任一迴路,所有支路電壓代數和恆等於零。
如何理解運放的虛短和虛斷?
虛短是本質,虛斷是派生。當然利用這兩個運放的性質,算是把運放當作理想運放看待,不過實際中應用兩個此性質計算出來的結果也相差無幾。
虛短是由於運放的開環放大倍數往往很高,而運放的輸出往往是有限的,這樣會導致輸入的兩個引腳間的電位差很小,近似於等電位。稱為虛短。
虛斷是由於運放的差模輸入電阻很高,流入的兩個輸入端的電流很小,近似於斷路,稱為虛斷。
溫度對晶體管的影響?
當溫度升高時,對於輸入特性,即Vbe與Ib之間的特性,會使得輸入特性曲線左移。
當溫度升高時,對於輸出特性,即Vce與Ic之間的特性,會使得輸出特性曲線上移。
PDN網路最根本原則?
當溫要使得各個晶元的電壓穩定,應使得PDN阻抗低於目標阻抗,PDN阻抗 ≤ 目標阻抗 = Vdd * ripple % / Itransient = 2 * Vdd * Vdd ripple % / P 。
運放如何選擇,其中需要注意哪些參數?
運放選擇時需要注意以下幾個參數:
共模抑制比(KCMR),帶寬,供電電壓,共模輸入范圍,輸入失調電壓(offset voltage),輸入失調電流(offset current),輸入偏置電流(bias current),壓擺率,溫漂。
共模抑制比:放大差模信號的能力,抑制共模信號的能力,體現抵抗雜訊的能力。
供電電壓:當進行小信號放大時,不能超過供電電壓的供電范圍,否則會產生信號的失真。
共模輸入范圍:此參數絕對了輸入信號的范圍,一般共模輸入范圍在手冊中會有規定,比如VCC – 0.2V,-VCC + 0.2V等,若是超過此共模輸入范圍,也會使得信號失真。
輸入失調電壓:在輸入電壓為0時,運放本應輸出電壓也為0V,但是由於運放內部不肯能絕對對稱,會有一定的電壓輸出,為了調節輸出為0時的電壓大小為失調電壓。一般失調電壓都在uV級別。
輸入失調電流:在輸入電壓為0時,流入兩個輸入端電流的差值,這體現了運放的輸入級差分管的不對稱性,希望此失調電流越小越好。
輸入偏置電流:流入運放兩輸入端的電流的均值 I = (Ibn + Ibp)/ 2。
阻抗與哪些因素有關?
阻抗與介質厚度,線間距,線寬,銅厚,介電材料有關。
其中與介質厚度和線間距成正比,主要是因為由瞬時阻抗可知Z = 83 * (根號下 介電常數) /CL,由於電容的值與導線距參考平面的高度成反比,所以,當導線距離參考平面比較近時,C變大,反之變小,所以Z的阻抗與介質厚度成正比,若介質厚度增大,則Z增大,反之亦然。經驗法則,厚度每增加1mil,特性阻抗減小2Ω。
線間距主要是從自感和互感方面考慮,首先線間距越小,互感增強,自感減小,會導致迴路電感減小,這也是差分信號為什麼要挨近的原因。當間距變小時整個迴路的電感減小,根據 阻抗和電感與電容之間的關系, Z = 根號下(L/C),所以假設導線距離參考平面距離不變的情況下,Z是減小的。所以阻抗Z與線間距成正比。
介電材料,介電材料本身其實不會影響阻抗,但是介電材料會影響電容特性,電容與介電材料成正比,所以阻抗Z與介電常數成反比。
銅厚與電感參量有關,銅厚與厚,電感的值越小,Z = 根號下(L/C),所以假設導線距離參考平面距離不變的情況下,Z是減小的。所以阻抗Z與銅厚成反比。
線寬與電感參量和電容量有關,線越寬,L減小,由於C的值與線寬成正比(也就是橫截面面積增大),Z = 根號下(L/C),所以假設導線距離參考平面距離不變的情況下,Z是減小的。所以阻抗Z與線寬成反比。
幾個重要性質,電感L與線間距,半徑成反比,與導線長度成正比。電容與介電常數,線寬成正比,與介質厚度成反比。
電感L的公式可以參看相關的資料。
C = 介電常數 * A / H。其中A為橫截面積,H為介質厚度。
R = ρ/A,其中電阻與線寬是成反比,所以大面積鋪銅也是基於這個道理,使得迴路阻抗盡可能小,減小地彈和壓降。
傳輸線阻抗為什麼是50Ω?
對於傳輸線,若是半徑選的太大,根據特性阻抗與L,R,C的關系,L會減小,C會增大,會導致特性阻抗變低,導致信號的衰減很大,權衡利弊,選50Ω時信號的衰減比較小。
對於邏輯門電路的扇出數如何確定
首先要確定兩個參數,第一個是雜訊容限,驅動門的高電平門限必須高於扇出門的高電平,驅動門的低電平門限必須小於扇出門的低電平。再者需要考慮拉電流和灌電流, 由拉電流參數確定 驅動門數為 N = IOH / IIH,由灌電流參數確定 驅動門數為 N = IOL / IIL,兩者取最小者為最大扇出數。
G. 面試 linux 文件系統怎樣io到底層
前言:本文主要講解LinuxIO調度層的三種模式:cfp、deadline和noop,並給出各自的優化和適用場景建議。IO調度發生在Linux內核的IO調度層。這個層次是針對Linux的整體IO層次體系來說的。從read()或者write()系統調用的角度來說,Linux整體IO體系可以分為七層,它們分別是:VFS層:虛擬文件系統層。由於內核要跟多種文件系統打交道,而每一種文件系統所實現的數據結構和相關方法都可能不盡相同,所以,內核抽象了這一層,專門用來適配各種文件系統,並對外提供統一操作介面。文件系統層:不同的文件系統實現自己的操作過程,提供自己特有的特徵,具體不多說了,大家願意的話自己去看代碼即可。頁緩存層:負責真對page的緩存。通用塊層:由於絕大多數情況的io操作是跟塊設備打交道,所以Linux在此提供了一個類似vfs層的塊設備操作抽象層。下層對接各種不同屬性的塊設備,對上提供統一的BlockIO請求標准。IO調度層:因為絕大多數的塊設備都是類似磁碟這樣的設備,所以有必要根據這類設備的特點以及應用的不同特點來設置一些不同的調度演算法和隊列。以便在不同的應用環境下有針對性的提高磁碟的讀寫效率,這里就是大名鼎鼎的Linux電梯所起作用的地方。針對機械硬碟的各種調度方法就是在這實現的。塊設備驅動層:驅動層對外提供相對比較高級的設備操作介面,往往是C語言的,而下層對接設備本身的操作方法和規范。塊設備層:這層就是具體的物理設備了,定義了各種真對設備操作方法和規范。有一個已經整理好的[LinuxIO結構圖],非常經典,一圖勝千言:我們今天要研究的內容主要在IO調度這一層。它要解決的核心問題是,如何提高塊設備IO的整體性能?這一層也主要是針對機械硬碟結構而設計的。眾所周知,機械硬碟的存儲介質是磁碟,磁頭在碟片上移動進行磁軌定址,行為類似播放一張唱片。這種結構的特點是,順序訪問時吞吐量較高,但是如果一旦對碟片有隨機訪問,那麼大量的時間都會浪費在磁頭的移動上,這時候就會導致每次IO的響應時間變長,極大的降低IO的響應速度。磁頭在碟片上尋道的操作,類似電梯調度,實際上在最開始的時期,Linux把這個演算法命名為Linux電梯演算法,即:如果在尋道的過程中,能把順序路過的相關磁軌的數據請求都「順便」處理掉,那麼就可以在比較小影響響應速度的前提下,提高整體IO的吞吐量。這就是我們為什麼要設計IO調度演算法的原因。目前在內核中默認開啟了三種演算法/模式:noop,cfq和deadline。嚴格算應該是兩種:因為第一種叫做noop,就是空操作調度演算法,也就是沒有任何調度操作,並不對io請求進行排序,僅僅做適當的io合並的一個fifo隊列。目前內核中默認的調度演算法應該是cfq,叫做完全公平隊列調度。這個調度演算法人如其名,它試圖給所有進程提供一個完全公平的IO操作環境。註:請大家一定記住這個詞語,cfq,完全公平隊列調度,不然下文就沒法看了。cfq為每個進程創建一個同步IO調度隊列,並默認以時間片和請求數限定的方式分配IO資源,以此保證每個進程的IO資源佔用是公平的,cfq還實現了針對進程級別的優先順序調度,這個我們後面會詳細解釋。查看和修改IO調度演算法的方法是:cfq是通用伺服器比較好的IO調度演算法選擇,對桌面用戶也是比較好的選擇。但是對於很多IO壓力較大的場景就並不是很適應,尤其是IO壓力集中在某些進程上的場景。因為這種場景我們需要的滿足某個或者某幾個進程的IO響應速度,而不是讓所有的進程公平的使用IO,比如資料庫應用。deadline調度(最終期限調度)就是更適合上述場景的解決方案。deadline實現了四個隊列:其中兩個分別處理正常read和write,按扇區號排序,進行正常io的合並處理以提高吞吐量。因為IO請求可能會集中在某些磁碟位置,這樣會導致新來的請求一直被合並,可能會有其他磁碟位置的io請求被餓死。另外兩個處理超時read和write的隊列,按請求創建時間排序,如果有超時的請求出現,就放進這兩個隊列,調度演算法保證超時(達到最終期限時間)的隊列中的請求會優先被處理,防止請求被餓死。不久前,內核還是默認標配四種演算法,還有一種叫做as的演算法(Anticipatoryscheler),預測調度演算法。一個高大上的名字,搞得我一度認為Linux內核都會算命了。結果發現,無非是在基於deadline演算法做io調度的之前等一小會時間,如果這段時間內有可以合並的io請求到來,就可以合並處理,提高deadline調度的在順序讀寫情況下的數據吞吐量。其實這根本不是啥預測,我覺得不如叫撞大運調度演算法,當然這種策略在某些特定場景差效果不錯。但是在大多數場景下,這個調度不僅沒有提高吞吐量,還降低了響應速度,所以內核乾脆把它從默認配置里刪除了。畢竟Linux的宗旨是實用,而我們也就不再這個調度演算法上多費口舌了。1、cfq:完全公平隊列調度cfq是內核默認選擇的IO調度隊列,它在桌面應用場景以及大多數常見應用場景下都是很好的選擇。如何實現一個所謂的完全公平隊列(CompletelyFairQueueing)?首先我們要理解所謂的公平是對誰的公平?從操作系統的角度來說,產生操作行為的主體都是進程,所以這里的公平是針對每個進程而言的,我們要試圖讓進程可以公平的佔用IO資源。那麼如何讓進程公平的佔用IO資源?我們需要先理解什麼是IO資源。當我們衡量一個IO資源的時候,一般喜歡用的是兩個單位,一個是數據讀寫的帶寬,另一個是數據讀寫的IOPS。帶寬就是以時間為單位的讀寫數據量,比如,100Mbyte/s。而IOPS是以時間為單位的讀寫次數。在不同的讀寫情境下,這兩個單位的表現可能不一樣,但是可以確定的是,兩個單位的任何一個達到了性能上限,都會成為IO的瓶頸。從機械硬碟的結構考慮,如果讀寫是順序讀寫,那麼IO的表現是可以通過比較少的IOPS達到較大的帶寬,因為可以合並很多IO,也可以通過預讀等方式加速數據讀取效率。當IO的表現是偏向於隨機讀寫的時候,那麼IOPS就會變得更大,IO的請求的合並可能性下降,當每次io請求數據越少的時候,帶寬表現就會越低。從這里我們可以理解,針對進程的IO資源的主要表現形式有兩個:進程在單位時間內提交的IO請求個數和進程佔用IO的帶寬。其實無論哪個,都是跟進程分配的IO處理時間長度緊密相關的。有時業務可以在較少IOPS的情況下佔用較大帶寬,另外一些則可能在較大IOPS的情況下佔用較少帶寬,所以對進程佔用IO的時間進行調度才是相對最公平的。即,我不管你是IOPS高還是帶寬佔用高,到了時間咱就換下一個進程處理,你愛咋樣咋樣。所以,cfq就是試圖給所有進程分配等同的塊設備使用的時間片,進程在時間片內,可以將產生的IO請求提交給塊設備進行處理,時間片結束,進程的請求將排進它自己的隊列,等待下次調度的時候進行處理。這就是cfq的基本原理。當然,現實生活中不可能有真正的「公平」,常見的應用場景下,我們很肯能需要人為的對進程的IO佔用進行人為指定優先順序,這就像對進程的CPU佔用設置優先順序的概念一樣。所以,除了針對時間片進行公平隊列調度外,cfq還提供了優先順序支持。每個進程都可以設置一個IO優先順序,cfq會根據這個優先順序的設置情況作為調度時的重要參考因素。優先順序首先分成三大類:RT、BE、IDLE,它們分別是實時(RealTime)、最佳效果(BestTry)和閑置(Idle)三個類別,對每個類別的IO,cfq都使用不同的策略進行處理。另外,RT和BE類別中,分別又再劃分了8個子優先順序實現更細節的QOS需求,而IDLE只有一個子優先順序。另外,我們都知道內核默認對存儲的讀寫都是經過緩存(buffer/cache)的,在這種情況下,cfq是無法區分當前處理的請求是來自哪一個進程的。只有在進程使用同步方式(syncread或者syncwirte)或者直接IO(DirectIO)方式進行讀寫的時候,cfq才能區分出IO請求來自哪個進程。所以,除了針對每個進程實現的IO隊列以外,還實現了一個公共的隊列用來處理非同步請求。當前內核已經實現了針對IO資源的cgroup資源隔離,所以在以上體系的基礎上,cfq也實現了針對cgroup的調度支持。總的來說,cfq用了一系列的數據結構實現了以上所有復雜功能的支持,大家可以通過源代碼看到其相關實現,文件在源代碼目錄下的block/cfq-iosched.c。1.1cfq設計原理在此,我們對整體數據結構做一個簡要描述:首先,cfq通過一個叫做cfq_data的數據結構維護了整個調度器流程。在一個支持了cgroup功能的cfq中,全部進程被分成了若干個contralgroup進行管理。每個cgroup在cfq中都有一個cfq_group的結構進行描述,所有的cgroup都被作為一個調度對象放進一個紅黑樹中,並以vdisktime為key進行排序。vdisktime這個時間紀錄的是當前cgroup所佔用的io時間,每次對cgroup進行調度時,總是通過紅黑樹選擇當前vdisktime時間最少的cgroup進行處理,以保證所有cgroups之間的IO資源佔用「公平」。當然我們知道,cgroup是可以對blkio進行資源比例分配的,其作用原理就是,分配比例大的cgroup佔用vdisktime時間增長較慢,分配比例小的vdisktime時間增長較快,快慢與分配比例成正比。這樣就做到了不同的cgroup分配的IO比例不一樣,並且在cfq的角度看來依然是「公平「的。選擇好了需要處理的cgroup(cfq_group)之後,調度器需要決策選擇下一步的service_tree。service_tree這個數據結構對應的都是一系列的紅黑樹,主要目的是用來實現請求優先順序分類的,就是RT、BE、IDLE的分類。每一個cfq_group都維護了7個service_trees,其定義如下:其中service_tree_idle就是用來給IDLE類型的請求進行排隊用的紅黑樹。而上面二維數組,首先第一個維度針對RT和BE分別各實現了一個數組,每一個數組中都維護了三個紅黑樹,分別對應三種不同子類型的請求,分別是:SYNC、SYNC_NOIDLE以及ASYNC。我們可以認為SYNC相當於SYNC_IDLE並與SYNC_NOIDLE對應。idling是cfq在設計上為了盡量合並連續的IO請求以達到提高吞吐量的目的而加入的機制,我們可以理解為是一種「空轉」等待機制。空轉是指,當一個隊列處理一個請求結束後,會在發生調度之前空等一小會時間,如果下一個請求到來,則可以減少磁頭定址,繼續處理順序的IO請求。為了實現這個功能,cfq在service_tree這層數據結構這實現了SYNC隊列,如果請求是同步順序請求,就入隊這個servicetree,如果請求是同步隨機請求,則入隊SYNC_NOIDLE隊列,以判斷下一個請求是否是順序請求。所有的非同步寫操作請求將入隊ASYNC的servicetree,並且針對這個隊列沒有空轉等待機制。此外,cfq還對SSD這樣的硬碟有特殊調整,當cfq發現存儲設備是一個ssd硬碟這樣的隊列深度更大的設備時,所有針對單獨隊列的空轉都將不生效,所有的IO請求都將入隊SYNC_NOIDLE這個servicetree。每一個servicetree都對應了若干個cfq_queue隊列,每個cfq_queue隊列對應一個進程,這個我們後續再詳細說明。cfq_group還維護了一個在cgroup內部所有進程公用的非同步IO請求隊列,其結構如下:非同步請求也分成了RT、BE、IDLE這三類進行處理,每一類對應一個cfq_queue進行排隊。BE和RT也實現了優先順序的支持,每一個類型有IOPRIO_BE_NR這么多個優先順序,這個值定義為8,數組下標為0-7。我們目前分析的內核代碼版本為Linux4.4,可以看出,從cfq的角度來說,已經可以實現非同步IO的cgroup支持了,我們需要定義一下這里所謂非同步IO的含義,它僅僅表示從內存的buffer/cache中的數據同步到硬碟的IO請求,而不是aio(man7aio)或者linux的native非同步io以及lio機制,實際上這些所謂的「非同步」IO機制,在內核中都是同步實現的(本質上馮諾伊曼計算機沒有真正的「非同步」機制)。我們在上面已經說明過,由於進程正常情況下都是將數據先寫入buffer/cache,所以這種非同步IO都是統一由cfq_group中的async請求隊列處理的。那麼為什麼在上面的service_tree中還要實現和一個ASYNC的類型呢?這當然是為了支持區分進程的非同步IO並使之可以「完全公平」做准備嘍。實際上在最新的cgroupv2的blkio體系中,內核已經支持了針對bufferIO的cgroup限速支持,而以上這些可能容易混淆的一堆類型,都是在新的體系下需要用到的類型標記。新體系的復雜度更高了,功能也更加強大,但是大家先不要著急,正式的cgroupv2體系,在Linux4.5發布的時候會正式跟大家見面。我們繼續選擇service_tree的過程,三種優先順序類型的service_tree的選擇就是根據類型的優先順序來做選擇的,RT優先順序最高,BE其次,IDLE最低。就是說,RT里有,就會一直處理RT,RT沒了再處理BE。每個service_tree對應一個元素為cfq_queue排隊的紅黑樹,而每個cfq_queue就是內核為進程(線程)創建的請求隊列。每一個cfq_queue都會維護一個rb_key的變數,這個變數實際上就是這個隊列的IO服務時間(servicetime)。這里還是通過紅黑樹找到servicetime時間最短的那個cfq_queue進行服務,以保證「完全公平」。選擇好了cfq_queue之後,就要開始處理這個隊列里的IO請求了。這里的調度方式基本跟deadline類似。cfq_queue會對進入隊列的每一個請求進行兩次入隊,一個放進fifo中,另一個放進按訪問扇區順序作為key的紅黑樹中。默認從紅黑樹中取請求進行處理,當請求的延時時間達到deadline時,就從紅黑樹中取等待時間最長的進行處理,以保證請求不被餓死。這就是整個cfq的調度流程,當然其中還有很多細枝末節沒有交代,比如合並處理以及順序處理等等。1.2cfq的參數調整理解整個調度流程有助於我們決策如何調整cfq的相關參數。所有cfq的可調參數都可以在/sys/class/block/sda/queue/iosched/目錄下找到,當然,在你的系統上,請將sda替換為相應的磁碟名稱。我們來看一下都有什麼:這些參數部分是跟機械硬碟磁頭尋道方式有關的,如果其說明你看不懂,請先補充相關知識:back_seek_max:磁頭可以向後定址的最大范圍,默認值為16M。back_seek_penalty:向後定址的懲罰系數。這個值是跟向前定址進行比較的。以上兩個是為了防止磁頭尋道發生抖動而導致定址過慢而設置的。基本思路是這樣,一個io請求到來的時候,cfq會根據其定址位置預估一下其磁頭尋道成本。設置一個最大值back_seek_max,對於請求所訪問的扇區號在磁頭後方的請求,只要定址范圍沒有超過這個值,cfq會像向前定址的請求一樣處理它。再設置一個評估成本的系數back_seek_penalty,相對於磁頭向前定址,向後定址的距離為1/2(1/back_seek_penalty)時,cfq認為這兩個請求定址的代價是相同。這兩個參數實際上是cfq判斷請求合並處理的條件限制,凡事復合這個條件的請求,都會盡量在本次請求處理的時候一起合並處理。fifo_expire_async:設置非同步請求的超時時間。同步請求和非同步請求是區分不同隊列處理的,cfq在調度的時候一般情況都會優先處理同步請求,之後再處理非同步請求,除非非同步請求符合上述合並處理的條件限制范圍內。當本進程的隊列被調度時,cfq會優先檢查是否有非同步請求超時,就是超過fifo_expire_async參數的限制。如果有,則優先發送一個超時的請求,其餘請求仍然按照優先順序以及扇區編號大小來處理。fifo_expire_sync:這個參數跟上面的類似,區別是用來設置同步請求的超時時間。slice_idle:參數設置了一個等待時間。這讓cfq在切換cfq_queue或servicetree的時候等待一段時間,目的是提高機械硬碟的吞吐量。一般情況下,來自同一個cfq_queue或者servicetree的IO請求的定址局部性更好,所以這樣可以減少磁碟的定址次數。這個值在機械硬碟上默認為非零。當然在固態硬碟或者硬RAID設備上設置這個值為非零會降低存儲的效率,因為固態硬碟沒有磁頭定址這個概念,所以在這樣的設備上應該設置為0,關閉此功能。group_idle:這個參數也跟上一個參數類似,區別是當cfq要切換cfq_group的時候會等待一段時間。在cgroup的場景下,如果我們沿用slice_idle的方式,那麼空轉等待可能會在cgroup組內每個進程的cfq_queue切換時發生。這樣會如果這個進程一直有請求要處理的話,那麼直到這個cgroup的配額被耗盡,同組中的其它進程也可能無法被調度到。這樣會導致同組中的其它進程餓死而產生IO性能瓶頸。在這種情況下,我們可以將slice_idle=0而group_idle=8。這樣空轉等待就是以cgroup為單位進行的,而不是以cfq_queue的進程為單位進行,以防止上述問題產生。low_latency:這個是用來開啟或關閉cfq的低延時(lowlatency)模式的開關。當這個開關打開時,cfq將會根據target_latency的參數設置來對每一個進程的分片時間(slicetime)進行重新計算。這將有利於對吞吐量的公平(默認是對時間片分配的公平)。關閉這個參數(設置為0)將忽略target_latency的值。這將使系統中的進程完全按照時間片方式進行IO資源分配。這個開關默認是打開的。我們已經知道cfq設計上有「空轉」(idling)這個概念,目的是為了可以讓連續的讀寫操作盡可能多的合並處理,減少磁頭的定址操作以便增大吞吐量。如果有進程總是很快的進行順序讀寫,那麼它將因為cfq的空轉等待命中率很高而導致其它需要處理IO的進程響應速度下降,如果另一個需要調度的進程不會發出大量順序IO行為的話,系統中不同進程IO吞吐量的表現就會很不均衡。就比如,系統內存的cache中有很多臟頁要寫回時,桌面又要打開一個瀏覽器進行操作,這時臟頁寫回的後台行為就很可能會大量命中空轉時間,而導致瀏覽器的小量IO一直等待,讓用戶感覺瀏覽器運行響應速度變慢。這個low_latency主要是對這種情況進行優化的選項,當其打開時,系統會根據target_latency的配置對因為命中空轉而大量佔用IO吞吐量的進程進行限制,以達到不同進程IO佔用的吞吐量的相對均衡。這個開關比較合適在類似桌面應用的場景下打開。target_latency:當low_latency的值為開啟狀態時,cfq將根據這個值重新計算每個進程分配的IO時間片長度。quantum:這個參數用來設置每次從cfq_queue中處理多少個IO請求。在一個隊列處理事件周期中,超過這個數字的IO請求將不會被處理。這個參數只對同步的請求有效。slice_sync:當一個cfq_queue隊列被調度處理時,它可以被分配的處理總時間是通過這個值來作為一個計算參數指定的。公式為:time_slice=slice_sync+(slice_sync/5*(4-prio))。這個參數對同步請求有效。slice_async:這個值跟上一個類似,區別是對非同步請求有效。slice_async_rq:這個參數用來限制在一個slice的時間范圍內,一個隊列最多可以處理的非同步請求個數。請求被處理的最大個數還跟相關進程被設置的io優先順序有關。1.3cfq的IOPS模式我們已經知道,默認情況下cfq是以時間片方式支持的帶優先順序的調度來保證IO資源佔用的公平。高優先順序的進程將得到的時間片長度,而低優先順序的進程時間片相對較小。當我們的存儲是一個高速並且支持NCQ(原生指令隊列)的設備的時候,我們最好可以讓其可以從多個cfq隊列中處理多路的請求,以便提升NCQ的利用率。此時使用時間片的分配方式分配資源就顯得不合時宜了,因為基於時間片的分配,同一時刻最多能處理的請求隊列只有一個。這時,我們需要切換cfq的模式為IOPS模式。切換方式很簡單,就是將slice_idle=0即可。內核會自動檢測你的存儲設備是否支持NCQ,如果支持的話cfq會自動切換為IOPS模式。另外,在默認的基於優先順序的時間片方式下,我們可以使用ionice命令來調整進程的IO優先順序。進程默認分配的IO優先順序是根據進程的nice值計算而來的,計算方法可以在manionice中看到,這里不再廢話。2、deadline:最終期限調度deadline調度演算法相對cfq要簡單很多。其設計目標是:在保證請求按照設備扇區的順序進行訪問的同時,兼顧其它請求不被餓死,要在一個最終期限前被調度到。我們知道磁頭對磁碟的尋道是可以進行順序訪問和隨機訪問的,因為尋道延時時間的關系,順序訪問時IO的吞吐量更大,隨機訪問的吞吐量小。如果我們想為一個機械硬碟進行吞吐量優化的話,那麼就可以讓調度器按照盡量復合順序訪問的IO請求進行排序,之後請求以這樣的順序發送給硬碟,就可以使IO的吞吐量更大。但是這樣做也有另一個問題,就是如果此時出現了一個請求,它要訪問的磁軌離目前磁頭所在磁軌很遠,應用的請求又大量集中在目前磁軌附近。導致大量請求一直會被合並和插隊處理,而那個要訪問比較遠磁軌的請求將因為一直不能被調度而餓死。deadline就是這樣一種調度器,能在保證IO最大吞吐量的情況下,盡量使遠端請求在一個期限內被調度而不被餓死的調度器。
H. Java框架Netty的io結構是什麼這是面試題
主從Reactor多線程Nio結構,主從Reactor線程模型的特點是:服務端用於接收客戶端連接的不再是個1個單獨的NIO線程,而是一個獨立的NIO線程池。Acceptor接收到客戶端TCP連接請求處理完成後(可能包含接入認證等),將新創建的SocketChannel注冊到IO線程池(sub reactor線程池)的某個IO線程上,由它負責SocketChannel的讀寫和編解碼工作。Acceptor線程池僅僅只用於客戶端的登陸、握手和安全認證,一旦鏈路建立成功,就將鏈路注冊到後端subReactor線程池的IO線程上,由IO線程負責後續的IO操作。
利用主從NIO線程模型,可以解決1個服務端監聽線程無法有效處理所有客戶端連接的性能不足問題。
它的工作流程總結如下:
從主線程池中隨機選擇一個Reactor線程作為Acceptor線程,用於綁定監聽埠,接收客戶端連接;
Acceptor線程接收客戶端連接請求之後創建新的SocketChannel,將其注冊到主線程池的其它Reactor線程上,由其負責接入認證、IP黑白名單過濾、握手等操作;
步驟2完成之後,業務層的鏈路正式建立,將SocketChannel從主線程池的Reactor線程的多路復用器上摘除,重新注冊到Sub線程池的線程上,用於處理I/O的讀寫操作。
I. 面試題:Java框架Netty的io結構是什麼
主從Reactor多線程結構,主從Reactor線程模型的特點是:服務端用於接收客戶端連接的不再是個1個單獨的NIO線程,而是一個獨立的NIO線程池。Acceptor接收到客戶端TCP連接請求處理完成後(可能包含接入認證等),將新創建的SocketChannel注冊到IO線程池(sub reactor線程池)的某個IO線程上,由它負責SocketChannel的讀寫和編解碼工作。Acceptor線程池僅僅只用於客戶端的登陸、握手和安全認證,一旦鏈路建立成功,就將鏈路注冊到後端subReactor線程池的IO線程上,由IO線程負責後續的IO操作。
利用主從NIO線程模型,可以解決1個服務端監聽線程無法有效處理所有客戶端連接的性能不足問題。
它的工作流程總結如下:
從主線程池中隨機選擇一個Reactor線程作為Acceptor線程,用於綁定監聽埠,接收客戶端連接;
Acceptor線程接收客戶端連接請求之後創建新的SocketChannel,將其注冊到主線程池的其它Reactor線程上,由其負責接入認證、IP黑白名單過濾、握手等操作;
步驟2完成之後,業務層的鏈路正式建立,將SocketChannel從主線程池的Reactor線程的多路復用器上摘除,重新注冊到Sub線程池的線程上,用於處理I/O的讀寫操作。
J. 面試問:java有IO為什麼還要用POI
poi、jxl是針對M$ Office 格式的文件 讀寫的專門的工具庫。
io 基本的讀寫 二進制 、文本的類