2012-04-01 60 views
4

在用戶空間中,執行磁盤IO與鏈接C庫一樣容易,或者如果您喜歡冒險,可以直接執行系統調用。我想知道內核本身如何執行IO。磁盤IO操作如何通常在內核級程序集中查找?

換句話說,假設我假設在特權模式下運行裸機上的應用程序。我如何訪問通過SATA連接連接的磁盤硬件?我是否從預先確定的地址執行加載?是否有某種與io相關的指令?

回答

4

Linux有一個函數調用跟蹤器。我建議你跟蹤IO請求。

警告:以下是我自己寫的,沒有真正知道真實的細節。

基本上,你需要使用PCI API交談的磁盤設備設置直接內存訪問,因爲你不想在每次讀取磁盤塊(或以太網幀)一個字節。所以你告訴硬件一些內存區(從地址X開始,長度爲N字節)是DMA區。您還可以設置內存緩存,以便知道該區域內的數據可以在沒有CPU寫入的情況下進行更改,因此即使您是單處理器也是易變的。

假設硬件一次只支持一個DMA事務。然後,你發送的命令,如「讀取512字節扇區數X(即字節×< < 9通過((X + 1)< < 9)在盤的-1),放入DMA區域。當你完成,發出中斷「。磁盤控制器做它的事情(它有一個ARM CPU和所有東西),通過PCI跨接到北橋集線器,並通過它到RAM,繞過CPU。當寫入完成(或錯誤輸出)時,中斷觸發。發生這種情況時,您等待(當進程休眠時,內核運行其他進程)。數百萬的CPU週期後(10毫秒是2Ghz芯片的永久性),中斷觸發。通知操作系統讀取已完成。操作系統可以在RAM中看到數據。然後它將其複製到用戶進程內存中,或者它位於共享頁面中,並且用戶進程可以從那裏讀取它。用戶進程被恢復(當然,放在準備運行的隊列中,並最終在調度器感覺到時運行)。

通過將數據複製到DMA空間和傳輸命令「完成後從DMA區域中的數據寫入扇區號X磁盤和火災中斷」寫入工作。然後,磁盤可能會在完成寫入操作或從RAM讀取數據後立即觸發中斷,在這種情況下,fsync不會真正起作用,並且數據庫和文件系統會因電源故障而損壞。

OS塊緩存適用於整個4KB RAM的頁面,所以每次讀取8個扇區,但這個想法是一樣的。新磁盤有一個本地API,與4KB sectors一起使用,但這個想法是一樣的。 USB與PCI不同,但這個想法是相同的。各種高性能硬件都具有巧妙的API,可以加快這些速度,同時有多個事務處理以及對它們的排序進行各種控制。

卸載TCP/IP的網絡接口可能有圍繞數據包的API而不是以太網幀,因爲NIC理解TCP/IP標頭。

確實是網絡設備的塊設備隱藏翻譯的某處(硬件部分,固件部分,軟件部分)。

在Linux中,我的硬件,我覺得是這樣的:

當模塊sata_piix is loaded,它告訴設備的PCI設備ID支持和callsbacks操作系統應該使用的操作系統,在所有described結構。通用OS PCI拓撲代碼發現ID爲8086:27c0,ICH7的設備,並在driver's table中找到它,因此操作系統認爲這是該硬件的正確驅動程序。在該表中,驅動程序會發現它應該在稍後將此設備視爲an ICH6 SATA device。由於驅動程序聲稱它支持該設備,因此該驅動程序的設備爲OS registers

從那裏分配設備的控制區域和prepared。 DMA is set up。 (這允許控制器自己啓動PCI數據傳輸到RAM(當它有數據準備好時),而不是等待CPU啓動傳輸)。中斷處理程序are set up

的代碼是通用的,並支持硬件的許多代,按時間順序排列:

  1. PIO
  2. Single/Multi-word DMA
  3. UDMA
  4. SATA
  5. AHCI

所以很難閱讀。跟蹤會使它更容易。

1

這取決於很多東西。我對ARM的瞭解不多,但我會想象有一些outportb指令可以讓你通過總線發送數據。與I/O設備通信是供應商特定的,但通常內核可能會對設備的寄存器進行映射(在GPU幀緩衝區的情況下),或者只是通過I/O設備可以識別的總線發送請求(通常是設備特定的) 。並且請求通常只是包含起始扇區,長度和告訴總線I/O轉移到的地址的序列化結構信息。

如果你想在內核(Linux的例子)已經有創建的I/O結構,並提交到特定的設備,所以你不需要做自己的功能做這種事情。如果你正在編寫你自己的操作系統,我會建議看一看Linux源代碼,其中有許多體系結構的彙編級別的例子。