3

比方說,一個程序讀取文件F.txt,另一個方案是在同一時刻寫入該文件。這是怎麼回事(在操作系統級別),當我在讀/寫文件?

(當我想我將如何實現這個功能,如果我是一個系統程序員),我認識到,可以有歧義:

  1. 究竟會第一個節目看到了什麼?

  2. 哪裏第二個程序編寫新的字節? (即寫「到位」與寫入到一個新的文件,然後用新的文件替換舊文件)

  3. 多少程序可以寫入同時在相同的文件嗎?

    ..也許事情並不那麼明顯。

所以,我的問題是:

  1. 什麼讀/寫文件的功能主要策略是?

  2. 哪些支持哪些操作系統(Windows,Linux,Mac OS等)?

  3. 可以說,它是依賴於特定的編程語言? (我可以假設Java可以嘗試提供在所有支持的操作系統的一些統一的行爲)

回答

5

從磁盤/閃存單元到本地Java變量,單個字節的讀取有很長的路要走。這是一個單字節行進的路徑:

  1. 磁性板/快閃單元
  2. 內部硬盤緩衝器
  3. SATA/IDE總線
  4. SATA/IDE緩衝器
  5. PCI/PCI-X公交車
  6. 計算機的數據總線
  7. 通過DMA計算機的RAM
  8. OS Page-cache
  9. libc的讀緩存,也稱爲用戶空間fopen()讀取緩衝
  10. 本地Java變量

出於性能方面的原因,大多數由OS完成的文件緩衝保持在頁面緩存,存儲最近讀並在RAM上寫入文件內容。

這意味着,從您的Java代碼中每一個讀寫操作是從和你的本地緩存來完成:

FileInputStream fis = new FileInputStream("/home/vz0/F.txt"); 

// This byte comes from the user space buffer. 
int oneByte = fis.read(); 

一個頁面通常是內存4KB單塊。每個頁面都有一些特殊的標誌和屬性,其中之一就是「髒頁面」,這意味着頁面有一些修改後的數據不會寫入物理介質。

過了一段時間,當操作系統決定將髒數據清理回磁盤時,它會將數據以相反的方向發送。

每當兩種不同過程以相同的文件中寫入數據,所產生的行爲是:

  • 不可能,如果文件被鎖定。第二個進程將無法打開文件。
  • 未定義,如果在文件的同一區域寫入。
  • 預計,如果在文件的不同區域進行操作。

「區域」取決於您的應用程序使用的內部緩衝區大小。例如,在一個兩兆文件,兩個不同的過程可以寫爲:

  • 一個上的數據的第一1kB的(0; 1024)。
  • 上的數據的最後一個1kB的另一個(2096128; 2097152)只有當本地緩衝器的大小是兩兆字節

緩衝器將發生重疊和數據損壞。在Java上,您可以使用Channel IO來讀取文件,並精確控制內部發生了什麼。

許多事務性數據庫通過發出sync operation強制一些寫入從本地RAM緩衝區返回到磁盤。所有與單個文件相關的數據都會被刷新到磁盤或閃存單元,從而有效地確保電源故障時不會丟失數據。

最後,memory mapped file是一個內存區域,它使用戶進程可以直接從頁面緩存中讀寫,並繞過用戶空間緩衝。

頁面緩存系統對多任務protected mode操作系統的性能至關重要,而且每個現代操作系統(Windows NT向上,Linux,MacOS,* BSD)都支持所有這些功能。

0

策略可以高達文件系統。通常,SO通過在文件與光盤同步之前對文件進行緩存來關注避免I/O操作。從緩衝區讀取將看到以前保存的數據。因此,軟件和硬件之間的是緩衝層(例如MySQL的MyISAM引擎使用該層多)

在關閉文件時或當程序被調用等FSYNC(方法JVM同步文件描述符緩衝器到磁盤),但緩衝液可通過同步當它們超過規定的閾值時也是由SO來計算的。在JVM中,這當然是在所有支持的操作系統上統一的。