tft每日頭條

 > 科技

 > io系統屬于操作系統嗎

io系統屬于操作系統嗎

科技 更新时间:2024-08-13 11:07:25

操作系統訪問IO設備的過程,經曆過很多個層次,就像網絡層協議一樣,每一層幹每一層的事情,每一層又向上層提供接口,操作系統訪問IO設備的層次結構如下圖所示:

io系統屬于操作系統嗎(操作系統是如何訪問IO設備的)1

IO結構層次

因此,本篇文章分為5個部分,逐步闡述操作系統訪問IO設備的過程

  1. IO設備分類
  2. 設備控制器
  3. 設備驅動程序
  4. 内核IO子系統
  5. 操作系統控制IO設備的流程舉例
IO設備分類:

IO設備大緻分為塊設備,字符設備,網絡設備,定時器等,本篇文章主要關注的是塊設備,字符設備,網絡設備,這些設備是我們程序開發中經常涉及的部分。

塊設備:

塊設備将數據分隔成多個固定大小的塊進行存儲,塊是數據存儲的最小單位,每個塊的大小可以為512字節-65536字節,每個塊都有唯一的地址,因此塊設備是可以尋址的,每次讀寫塊設備的數據時,都是以塊為最小單位讀取或者寫入連續的多個塊。

例如磁盤就是塊設備,它的塊大小通常是512個字節等于磁盤的一個扇區的大小,因此一個扇區就是一個塊,磁盤的數據是由很多個扇區構成。

通常塊設備可以順序訪問或者随機訪問,應用程序訪問塊設備時,通常不是直接訪問的,而是通過文件系統,文件系統對塊設備進行統一管理,将塊設備的各類細節封裝起來,文件系統管理的是邏輯設備即文件,文件系統統一提供read,write,seek等接口間接訪問塊設備,文件系統将文件名和塊設備的每一個塊之間的映射關系隐藏起來,因此塊設備對于應用程序來說是透明。

當然有些特殊的應用程序例如數據庫管理系統可以直接訪問塊設備,對塊設備的每個塊采用專用的數據結構進行管理,以達到最佳的讀寫效率,這些專用的數據結構有B 樹,LSVM樹等,這些數據結構都有各自的應用場景。

字符設備:

字符設備是不可以存儲和不可以尋址的,字符設備每次讀入或者寫入一個字符,常見的字符設備包括鼠标,鍵盤,打印機等,操作系統通常會提供一些get或者put的方法來讀取或者寫入一個字節,通常會有标準庫對操作系統提供的get或者put方法進行封裝,例如增加了字符緩沖,支持字符流讀寫,支持按行讀,按行寫,編輯緩沖數據等。

網絡設備:

網絡設備通常用于發送或者接受網絡數據,這些網絡數據通常是網絡包的形式,不同于塊設備,操作系統會提供專門的網絡接口進行網絡數據的發送和接受,網絡接口通常就是socket,這個Socket是傳輸層協議的代理,我們通過socket就可以處理網絡數據了。

對于Socket它就像一個電源插座,任何電器都可以插入電源插座,一旦插入電源插座就可以通電,因此應用程序也可以用創建一個Socket,Socket分為服務端Socket和客戶端Socket,服務端Socket啟動後,會一直監聽來自客戶端Socket的來電,一旦接到來電就可以轉給一個接線員,這個接線員也是一個Socket,由它來負責與客戶端Socket的通信。

Socket通常支持BIO,NIO,AIO幾種模式,不同的操作系統支持的模式不同,通常都支持BIO和NIO,根據不同的應用場景可以選擇不同的模式,沒有絕對可言。

定時器:

定時器通常分為硬定時器和軟定時器。

硬定時器:

硬定時器通常是由晶體震蕩器,計數器和存儲寄存器組成,當把一塊石英晶體适當地切割後,并在它上加上一定的電壓後,它就可以非常精确地産生周期性的時鐘信号,這些信号的頻率可以是幾百赫茲,幾千赫茲等,這個頻率值跟所選的晶體類型有關。

硬定時器的基本原理是這樣的:

每個定時器會在存儲寄存器設置一個計數值,每次定時器啟動時,将這個計數值設置到計數器中,每次晶體震蕩後,産生一個時鐘信号,該信号被送入到計數器,計數器就減1,直到計數器變為0,那就表示定時器觸發了,它會給CPu發送一個時鐘中斷,CPU接收到這個中斷後會進入時鐘處理程序。

時鐘處理程序會進行一些防止進程時間片超時,進程CPU使用情況記賬,維護計算機時間,計算機硬件監控,進程性能數據剖析等工作。

硬件定時器可以分為一次性定時器和永久性定時器,一次性定時器表示定時器觸發後後,就自動停止了,永久性定時器則每次定時器觸發後,會将存儲寄存器中的計數值重新賦值給計數器,然後重新啟動定時器,一直運行,直到計算機關閉。

軟定時器:

有些高性能的工作需要高頻率地執行,例如一個高性能的網絡,網絡帶寬為千兆級别以上,為了保證高效率地輸出,每隔12us就要發送一個數據包,如果采用硬定時器,每隔12us産生中斷後,會進行一系列的處理,包括進程上下文,流水線,高速緩沖,TLB,MMU等重新切換等,這一繁雜的切換工作需要的時間可能已經接近12us,那麼這就意味着從中斷開始到真正開始發送數據包,會經過一段時間,這個時間對于一個高性能的網絡來說是不能容忍的,因此這種場景可以采用軟定時器,軟定時器不需要中斷,每次發送數據包時,會根據硬定時器 12us設置一個超時時間,每次發送完數據包切換到用戶态後,用戶程序檢查這個超時時間是不是已經過期了,如果過期了就立即發送一個數據包,對于這類高性能的場景,軟定時器比較合适,當然如果沒有要求那麼高的性能要求的話,一般的硬定時器中斷足夠應付了。

設備控制器:

操作系統是不直接操作IO設備,常常是通過設備控制器間接訪問IO設備,可以說設備控制器是CPU與IO設備的橋梁,設備控制器可以連接單個設備,也可以同時連接多個設備,如果連接多個設備,設備控制器和設備之間需要增加一個仲裁設備,這個仲裁設備負責仲裁設備控制器要和那個IO設備進行交互。

設備控制器負責的工作如下:

  • 負責控制IO設備,例如設備的讀,寫,打開,關閉等。
  • 協調CPU和IO設備速度讀寫速度的不匹配,例如設備控制器增加數據緩沖。
  • CPU和IO設備數據信号的轉換。
  • CPu時鐘頻率和IO設備時鐘頻率的協調和同步。
  • IO端口地址的譯碼,例如翻譯IO端口地址到具體的設備寄存器。

設備控制器提供了4種寄存器即狀态寄存器,數據輸入寄存器,數據輸出寄存器,控制寄存器,操作系統和設備控制器之間的交互就是通過這些設備寄存器,因此它們的交互方式類似于生産者和消費者的關系。

數據輸出寄存器:

操作系統可以将CPU寄存器的數據發送到數據輸出寄存器,設備控制器得知數據輸出寄存器有數據後,就将數據輸出寄存器的數據發送給IO設備。

數據輸入寄存器:

設備控制器讀入IO設備的數據後,存儲在數據輸入寄存器,然後操作系統讀取數據輸入寄存器的數據到CPU寄存器中。

狀态寄存器:

存儲設備相關的狀态,例如設備是否已經就緒,數據輸入寄存器是不是有數據了等,操作系統可以讀取該寄存器的值來查看設備的各類狀态。

控制寄存器:

操作系統可以寫入控制寄存器從而告知設備控制器執行什麼IO操作。

另外,為了協調CPU和IO設備的讀寫速度差異,設備控制器通常有數據緩沖,用于緩沖從設備讀入的數據,或者從操作系統寫入的數據,例如操作系統将數據寫入到數據輸出寄存器後,設備控制器将數據輸出寄存器的數據直接寫入到數據緩沖,而不是直接發送到IO設備,這個很好理解,因為設備控制器寫入數據到IO設備的速度與CPU的發送速度相比差異太大了。

操作系統怎麼讀寫設備寄存器呢,有兩種方式

1.IO指令

每個設備寄存器都有一個地址,它與内存的地址不同,這個地址稱為IO端口地址,操作系統支持的IO端口地址有65536個即0~64K-1,IO端口地址的範圍叫做IO端口空間,内存地址範圍叫做内存空間,因此IO端口空間與内存空間是獨立的。

假如CPU要讀取一個端口地址對應設備寄存器,過程如下:

1.CPU将IO端口地址放到地址總線上,然後在控制總線上設置一個READ信号,此時隻是CPU隻是要表明要讀取某個地址的數據了,至于這個地址來自哪個空間,還需要下一步操作。

2.CPU設備另外一條信号線,設置信号線要訪問IO端口空間。

3.所有的設備控制器接收到該信号線後,發現是訪問IO端口空間,就會檢查地址總線上的地址是不是自己的寄存器的地址,總有一個設備控制器接受這個地址,不是自己的地址設備控制器直接忽略這個信号。

下面表格為PC設備中常見的設備IO端口地址分布圖

IO端口範圍(十六進制)

設備

000-00F

DMA控制器

020-021

中斷控制器

200-20F

遊戲控制器

320-32F

硬盤控制器

3D0-3DF

圖形控制器

3F0-3F7

軟盤控制器

另外,CPU提供了專門的IO指令,通過IO指令發送内容到IO端口地址或者從IO端口地址獲取内容來實現設備寄存器的讀寫,

常見的IO指令有IN和OUT

IN AX,DX

DX寄存器存儲的是IO端口,該指令表示獲取IO端口指向的設備寄存器的内容到AX寄存器。

OUT DX,AX

DX寄存器存儲的IO端口,該指令表示将AX寄存器的内容寫入到IO端口指向的設備寄存器。

2.内存映射IO

CPU訪問任何數據都是通過地址總線,一個32位的地址總線可以尋址的範圍是4個G,從上文知道,如果有IO端口地址空間的話,需要單獨的一個信号線表明地址線訪問的那個空間,假設該信号線訪問的是内存空間。

這個内存空間内大部分地址分給了主存,還有一小部分地址落在了其它的内存或者設備寄存器,例如圖形控制器的數據緩沖,BIOS的ROM等,通常這部分地址在地址總線範圍的低地址處,如下圖

io系統屬于操作系統嗎(操作系統是如何訪問IO設備的)2

内存映射IO

因此通過内存映射IO,我們不需要專門的IO指令,直接通過内存相關的指令例如MOV,LOAD等命令就可以讀寫設備寄存器或者設備控制器的數據緩沖,當地址總線上寫入了地址後,主存,設備控制器,BIOS等都會檢查這個地址是不是屬于自己的範圍,如果是自己的範圍内的地址,就會接受這個地址,并且做出響應。

操作系統與設備控制器交互的方式通常有3種:

程序控制IO

程序控制IO也叫輪詢,假設CPU寫數據到IO設備,通常應用程序會在用戶空間分配一個緩沖,用戶緩沖要發送的數據,然後進行系統調用,通過系統調用,内核會将用戶緩沖拷貝到内核緩沖,這個内存緩沖可以認為是一個發送數組,然後對發送數組的每個字節逐個按照以下流程寫入到IO設備,流程如下圖所示:

io系統屬于操作系統嗎(操作系統是如何訪問IO設備的)3

CPU輪詢方式會一直檢查狀态寄存器,一直到狀态寄存器不忙時,才會寫入發送數組的當前字節到數據輸出寄存器,同時設置控制寄存器的寫位和就緒位,通知設備控制器要執行一個寫操作而且數據已經準備好了。

設備控制器檢查到控制寄存器的就緒位已經就緒後,會進一步檢查要執行什麼操作,發現寫位為1,就會從數據輸出寄存器獲取數據,寫到IO設備,完成後,就會清除控制寄存器的就緒位,忙位,故障位,這樣CPU就會繼續寫入數據了。

IO設備的寫速度與CPU相比差的十萬八千裡,因此CPU大部分的時間都在檢查狀态寄存器的忙位,浪費了大量的CPU時間,這也是輪詢方式最大的缺點。

中斷驅動IO

假設CPU寫數據到IO設備,通常應用程序會在用戶空間分配一個緩沖,用戶緩沖要發送的數據,然後進行系統調用,通過系統調用,内核會将用戶緩沖拷貝到内核緩沖,這個内存緩沖可以認為是一個發送數組,然後對發送數組的每個字節逐個按照以下流程寫入到IO設備,假設發送數組剩餘要發送的字節數為count,如下圖所示為中斷驅動IO的流程圖

io系統屬于操作系統嗎(操作系統是如何訪問IO設備的)4

由上圖所示分為3個子流程

CPU寫入流程:

CPU寫入流程與輪詢看起來有點類似,不一樣的地方在于,用戶進程在寫入第一個數據到寄存器後,就被阻塞了,CPU此時調度其它進程運行。

設備控制器流程:

這個流程與輪詢中的設備控制器流程比較類似,不同的是,設備控制器寫數據到IO設備後,會發送一個設備中斷信号給CPU,通知CPU可以繼續發送數據了。

CPU中斷處理程序:

每次CPU執行時,會先檢查中斷線上是不是有中斷信号,如果有中斷信号,就會去執行中斷處理程序,對于設備的中斷處理程序,如果沒有發送的數據了,就将用戶進程加入到CPU的就緒隊列中,CPU後續會調度用戶進程,阻塞就解除了,調用就返回了,如果有發送的數據,就繼續發送到設備控制器的寄存器中。

中斷處理程序返回後,會被切換到被中斷的進程,繼續執行。

中斷驅動IO相比輪詢來說,不需要CPU一直等IO設備寫入完成,而是可以将寫入寄存器後,直接阻塞,調度其它的進程來使用CPU,當IO設備寫入完成後,發送中斷信号,通知CPU,CPU執行中斷處理程序繼續寫入下一個字節,最終發送完成後,解除阻塞,這樣CPU就可以充分利用,減少了CPU的浪費。

DMA

假設CPU寫數據到IO設備,通常應用程序會在用戶空間分配一個緩沖,用戶緩沖要發送的數據,然後進行系統調用,通過系統調用,内核會将用戶緩沖拷貝到内核緩沖,這個内存緩沖可以認為是一個發送數組。

DMA的處理流程如下:

io系統屬于操作系統嗎(操作系統是如何訪問IO設備的)5

DMA

DMA的處理流程也可以分為3個子流程

CPU流程 :

CPU傳輸發送數組的起始地址,發送數組的大小給DMA,此時用戶進程A就從CPU運行隊列移除,此時用戶進程A阻塞,CPU調度其它的進程運行。

DMA流程:

DMA根據發送數組的起始地址,檢查尚未發送的字節數count,如果count<0, 那麼就是傳輸數據給設備寄存器,然後就等待設備控制器的應答,如果 count=0,那麼DMA發送完成了,它會給CPU發送一個中斷信号,CPU收到這個中斷信号後,會執行DMA的中斷處理程序,将用戶進程A加入到CPU的就緒隊列,後續CPU會調度用戶進程A去運行,這個時候用戶進程A調用返回。

設備控制器流程:

設備控制器的流程與輪詢和中斷類似,隻是設備控制器發送完數據後,會發送一個應答給DMA,DMA收到這個應答後,會将coun-1,然後調度發送下一個字節。

可以看出DMA不需要設備控制器發送中斷給CPU,它成為了CPU的代理,CPU可以專注地做其它的事情,隻是DMA傳輸完成後,才會中斷一下CPU。

另外DMA每次控制設備控制器寫數據時,都會先控制住地址總線,這樣就會跟CPU搶時鐘周期,這個也是不可以避免的。

DMA控制器可以連接多個設備控制器,通過一定的算法,來切換每次控制的設備控制器,另外複雜一些的DMA控制器也可以一次控制設備控制器發送多個字節,這樣一次性占據地址總線的時間就比較長,這樣的效率也會更高,隻是CPU如果此時需要用地址總線,那就需要等待一段時間了,CPU周期被浪費了。

設備驅動程序

我們上面闡述操作系統通過控制設備控制器來間接控制IO設備,其實就是設備驅動程序來控制設備控制器。

設備驅動程序通常位于内核,它封裝對設備控制器操作的所有細節和差異,并且提供了标準的接口供内核的IO子系統調用,這一點類似于網絡協議的分層結構,每一層将數據封裝好後提供給上一層使用,上一層不用考慮下一層的實現細節。

可以說設備驅動程序将硬件和IO子系統調用分離開來,每一類設備都需要專門的設備驅動程序進行控制,一般這些設備驅動程序都是由設備提供商來負責編寫,通常不同的操作系統設備驅動程序都有不同的開發标準,因此隻要設備提供商按照操作系統要求的标準開發設備驅動程序,增加任何的IO設備和控制器對于操作系統來說都是透明的,當然這對操作系統來說好處多多,對于設備提供商來說好處不多,他們需要為各種操作系統系統編寫驅動程序,這樣才能争取不同操作系統的用戶。

通常設備驅動程序不添加任何用戶策略,隻負責與硬件打交道,它通常會将上層IO子系統發送過來的抽象的讀寫請求,轉化為實際的對硬件的IO操作,保證硬件可用并提供硬件原始數據,原始的數據交由IO子系統進行二次加工,IO子系統再根據根據各類用戶策略對原始數據進行處理。

IO子系統

IO子系統位于内核,處于設備驅動程序的上一層,它是設備無關的,主要提供文件系統,IO調度,緩沖,高速緩沖,設備保護,錯誤處理等。

增加新的設備驅動程序對IO子系統沒有i影響,因為每個設備驅動程序向IO子系統提供标準的訪問接口。

文件系統:

文件系統主要負責對塊設備進行統一管理,抽象出文件這個邏輯設備的概念,建立文件與塊設備的每個塊的映射關系等,文件系統也負責根據文件名定位到設備驅動程序和具體的某個設備,這個以後單獨寫文章闡述。

IO調度

操作系統為每個設備維護一個IO請求隊列,當進程進行IO請求時,會将這些IO請求加入到這個隊列中,如果按照先進先出的方式順序訪問設備,從系統總體來講,并不一定是高效的,通常需要合适的IO調度算法來高效和充分地利用設備。

另外不同的IO請求有不同的優先級,有些IO請求優先級天生比較高,它可以獲得優先執行的權利,例如一個缺頁IO請求就比其它的普通應用程序的請求更加緊急,也會有更高的優先級。

緩沖

采用緩沖有以下幾個理由:

一:設備控制器通常有單獨的數據緩沖,應用程序也需要有自己的緩沖,應用程序寫數據時,通常寫入到自己的緩沖,而不是直接寫到設備控制器的緩沖,這是由于IO設備處理數據較慢,設備控制器的緩沖,很容易就滿了,因此應用程序設置自己的緩沖,這樣即使設備控制器緩沖滿了,應用程序照樣可以寫數據,不至于阻塞,另外應用程序設置自己的緩沖,可以靈活增加緩沖的容量,也可以設置多個緩沖,例如雙緩沖,循環緩沖等。

.通常應用程序自己的緩沖在用戶空間,操作系統可以将用戶緩沖中的數據發送到設備控制器上的數據緩沖,設備控制器再發送數據緩沖的數據到設備,這樣有兩個問題,一個是:用戶空間的緩沖通常是在用戶空間的某些頁上,一旦這些頁被換出了,操作系統讀取這些頁的數據時發現頁不在就會進行缺頁處理,這個很影響效率,另外一個是:操作系統發送數據時,用戶空間的緩沖被修改了,此時就造成了數據的破壞,因此通常操作系統會在内核開辟一塊空間叫做内核緩沖,應用程序寫入數據時,先将用戶緩沖複制到内核緩沖,内核緩沖再寫入到設備控制器的數據緩沖,此後内核就可以放心地發送數據了,不用擔心頁被換出或者數據被修改了,這樣的複制非常影響效率,因此有些操作系統會采用虛拟内存映射和寫時複制的方式将用戶緩沖和内核緩沖指向内核的一塊共享緩沖,如果用戶修改了共享緩沖,會通過寫時複制的方式,拷貝修改的部分到用戶空間,不影響原來的共享緩沖。

整體來說緩沖不光是寫出的緩沖,讀入的緩沖也是同樣的道理,這裡不再闡述。

高速緩存:

操作系統可以開辟一塊内存,用于存儲熱點的設備數據,采用一定的緩存失效算法,剔除失效的緩存,這樣可以每次進行IO讀取操作時,則可以直接從高速緩存中獲取,不在進行任何IO操作。

有時候高速緩存和緩沖可以合二為一,例如一個寫緩沖存儲了要寫出到設備的數據,此時如果再讀取這些數據時,就可以把寫緩沖當做高速緩沖,直接從寫緩沖讀取。

設備保護:

IO設備保護有以下幾種方式:

1.IO特權指令,IO指令通常都是特權指令,這些指令隻有操作系統才可執行,這樣就杜絕了應用程序執行IO指令,應用程序可以通過系統調用進行IO操作。

2.通過内存映射IO方式訪問設備控制器數據緩沖或者設備寄存器時,地址總線上一部分地址用于映射到設備控制器數據緩沖或者設備寄存器,這部分地址由操作系統的内存保護模塊進行控制,禁止用戶空間訪問這些地址。

3.IO子系統中文件系統中所有的文件都有訪問的權限,限制文件的訪問就間接地對文件對應的IO設備進行了保護。

錯誤處理:

IO設備産生的錯誤往往比較多而且雜,當錯誤發生時,IO子系統會盡最大努力對這些錯誤進行處理,許多IO錯誤與特定的設備有關,這類的錯誤隻能交由設備驅動程序去處理,但IO子系統有個錯誤處理的流程,按照這個流程進行處理是通用的和設備無關的,以下為錯誤處理框架中的幾個關鍵環節的處理過程。

一:一些IO類的錯誤是編程導緻的,比如應用程序對鍵盤,掃描儀,鼠标進行寫入操作,這些設備是不支持寫入的,還有就是應用程序提供了一個無效的緩沖區或者參數,這些編程導緻的錯誤,IO子系統直接返回相應的錯誤碼給應用程序。

二:另外一種IO類的錯誤就是設備确實有問題了,例如應用程序試圖寫入一個損壞的磁盤塊,這類錯誤交由設備驅動程序解決,如果設備驅動程序實在不知道怎麼解決,則再返回IO子系統,由IO子系統返回給應用程序。

三:還有一些IO類錯誤可以交由用戶去決定怎麼去解決,例如一個讀磁盤發生錯誤,可以由IO子系統告知用戶,例如彈出一個對話框,讓用戶去選擇重試次數,忽略錯誤,或者幹脆停掉進程。

操作系統訪問IO設備的流程舉例

假設應用程序進行一個系統調用read讀取磁盤數據,這個read是阻塞的,設備驅動程序與設備控制器交互方式采用DMA,下面來闡述下整個流程如下圖所示:

io系統屬于操作系統嗎(操作系統是如何訪問IO設備的)6

1.IO子系統根據文件名可以定位到設備驅動程序,設備寄存器端口,磁盤物理地址,每個操作系統有各自的實現方式,通常這一部分通常由文件系統來實現。

2.IO子系統根據磁盤物理地址去高速緩沖中查找,如果高速緩沖命中,則将高速緩沖中的數據拷貝到用戶空間緩沖,調用返回。

5.IO子系統将應用程序A從CPU的運行隊列移除,加入到設備的等待隊列,這個時候應用程序阻塞了。

6~8.IO子系統根據設備寄存器端口和磁盤物理地址封裝IO請求,将IO請求加入到設備IO請求隊列中,IO子系統根據IO請求調度算法,開始調用IO請求,最終将應用進程A的IO請求發送給設備驅動程序。

9~11.設備驅動程序在内核空間開辟一塊内存空間,作為内核緩沖,這塊内核緩沖用來接收來自磁盤的數據,然後設備驅動程序控制DMA,發送控制請求給DMA,然後設備驅動程序阻塞了,阻塞的方法有很多中,比如wait。

12.DMA控制磁盤控制器,完成讀取數據後,發送中斷信号給CPU。

13.CPU接受到中斷信号後,開始執行中斷處理程序,程序會檢查IO請求是否已經完成,請求的完成狀态等,然後封裝IO請求結果,發送給IO子系統。

14. IO子系統收到請求結果後,會喚醒設備驅動程序,喚醒的方式比如singal,同時IO子系統會拷貝内核緩沖的數據到用戶緩沖,同時将返回結果設置到應用程序A的用戶空間。

15.IO子系統将應用程序A從設備隊列中移除,加入到CPU就緒隊列中。

16.CPU調度運行應用進程A,應用進程A将返回結果返回。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved