国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

linux IO刷新機制sync, fsync, fdatasync和fflush詳解及注意事項

2019-11-08 03:12:06
字體:
來源:轉載
供稿:網友

stackoverflow:

http://stackoverflow.com/questions/2340610/difference-between-fflush-and-fsync

fflush() works on FILE*, it just flushes the internal buffers in the FILE* of your application out to the OS.

fsync works on a lower level, it tells the OS to flush its buffers to the physical media.

OSs heavily cache data you write to a file. If the OS enforced every write to hit the drive, things would be very slow. fsync (among other things) allows you to control when the data should hit the drive.

Furthermore, fsync/commit works on a file descriptor. It has no knowledge of a FILE*and can't flush its buffers. FILE* lives in your application, file descriptors live in the OS kernel, typically.

轉載原文:http://blog.csdn.net/lmh12506/article/details/25604793

介紹:

        linux,unix在內核中設有 緩沖區高速緩沖或頁面高速緩沖,大多數磁盤I/O都通過緩沖進行,采用延遲寫技術。sync:將所有修改過的快緩存區排入寫隊列,然后返回,并不等待實際寫磁盤操作結束fsync:只對有文件描述符制定的單一文件起作用,并且等待些磁盤操作結束,然后返回。fdatasync:類似fsync,但它只影響文件的數據部分。fsync還會同步更新文件的屬性。fflush:標準I/O函數(如:fread,fwrite)會在內存建立緩沖,該函數刷新內存緩沖,將內容寫入內核緩沖,要想將其寫入磁盤,還需要調用fsync。(先調用fflush后調用fsync,否則不起作用)。

前面介紹函數write()時,我們認為該函數一旦返回,數據便已經寫到了文件中。但是這種概念只是宏觀上的。實際上,操作系統實現某些文件I/O時(如磁盤文件),為了保證I/O的效率,在內核通常會用到一片專門的區域(內存或獨立的I/O地址空間)作為I/O數據緩沖區。應用程序可以將這片內核區域看成是I/O數據的一個快速中轉站(圖3-5)。當調用write()函數寫出數據時,數據一旦寫到該緩沖區,函數便立即返回。此時寫出的數據可以用read()讀回,也可以被其他進程讀到,但是并不意味著它們已經被寫到了外部永久存儲介質上,即使調用close()關閉文件后也可能如此。內核I/O數據緩沖區中的數據只在適當的時候才由操作系統啟動外設進行傳輸,真正的傳輸動作由獨立于CPU的外設控制器或者外設本身(Linux稱之為DMA引擎)來完成。因此,從數據被實際寫到磁盤的角度來看,用write()寫出的文件數據與外部存儲設備并不是完全同步的。在現代計算機系統中,這種不同步的時間間隔非常短,一般只有幾秒或十幾秒,具體取決于寫出的數據量和I/O數據緩沖區的狀態。盡管不同步的時間間隔很短,但是如果在此期間發生掉電或者系統崩潰,則會導致所寫數據來不及寫至磁盤而丟失的情況。

由于現代計算機通常都十分穩定可靠,出現掉電或系統崩潰的情況極少,因此多數應用在寫文件時可以忽略這種瞬間不同步情況。但是,有些應用存在著這樣的一些同步點,在這些點上所寫的數據非常關鍵,或者必須及時保證文件的一致性。為了防備萬一,這些應用需要確保所有寫出的數據都已經傳送到了外部永久存儲介質上。為此,UNIX提供了兩種手段來實現這一目的。其中一種方法是對文件設置O_SYNC標志(表3-1),這樣可以保證每次寫數據都直接寫到磁盤。如果設置了這個標志,write()調用將直到數據已安全地寫到磁盤后(而不僅僅是系統的I/O緩沖區)才返回。但是這樣每次寫數據都保持同步的效率比較低。

 

另一種方法是只在需要時調用函數fsync()或者fdatasync()。#include <unistd.h>int fsync(int fildes);int fdatasync(int fildes)

fsync()強制與描述字fildes相連文件的所有修改過的數據(包括核內I/O緩沖區中的數據)傳送到外部永久介質,即刷新fildes給出的文件的所有信息。調用 fsync()的進程將阻塞直到設備報告傳送已經完成。這里“所有修改過的數據”包括用戶寫出的數據以及文件本身的特征數據(4.1.1節和表4-1),如文件的訪問時間、修改時間、文件的屬主等。

fdatasync()的功能與fsync()類似,只是它只強制傳送用戶已寫出的數據至物理存儲設備,不包括文件本身的特征數據。這樣可以適當減少文件刷新時的數據傳送量。不過有的系統并不支持fdatasync(),在這種系統上,fdatasync()等價于fsync()。

一個程序在寫出數據之后,如果繼續進行后續處理之前要求確保所寫數據已寫到磁盤,則應當調用fsync()。例如,數據庫應用通常會在調用write()保存關鍵交易數據的同時也調用fsync()。

我們在2.7節曾討論了標準I/O流緩沖區的問題以及函數fflush()。那么,這兩個緩沖區有何不同?回答是,內核I/O緩沖區是由操作系統管理的空間,而流緩沖區是由標準I/O庫管理的用戶空間。fflush()只刷新位于用戶空間中的流緩沖區。fflush()返回后,只保證數據已不在流緩沖區中,并不保證它們一定被寫到了磁盤。此時,從流緩沖區刷新的數據可能已被寫至磁盤,也可能還待在內核I/O緩沖區中。要確保流I/O寫出的數據已寫至磁盤,那么在調用fflush()后還應當調用fsync()。

總結

根據以上轉載的內容,并根據我實際的操作經驗,作個簡單的總結

所以可以看出fflush和fsync的調用順序應該是:c庫緩沖-----fflush---------〉內核緩沖--------fsync-----〉磁盤

請注意,fflush使buffer從c庫緩沖區刷到內核緩沖區是比較快速的,所以不會很大的影響當前線程,而fsync是將buffer寫入磁盤,影響當前線程的阻塞,所以使用fsync時要慎重考慮當前線程所執行的任務。

最近在查一個bug:行車記錄儀用了一小段時間后會特別卡,且最終進程被oom_killer給kill了,最終發現問題是在fdatasync的使用上。應用使用了兩個線程進入工作,一個線程專門負責寫文件,一個線程專門負責添加視頻幀,它們之間通過一個配置了一個寫指針和一個讀指針的循環鏈表進行工作,當分配的內存不夠時,會自動分配內存。由于在寫文件的線程中,fwrite()了一段內容后,調用fdatasync函數。這就有問題了,由于調用了fdatasync函數,嚴重地阻塞了當前線程,使讀指針一直未增加,導致分配的內存不夠,于是繼續申請內存,最終一段時間之后,由于申請了太多的內存,系統調用oom_killer殺死了我們的進程(說多了都是淚,還以為是內存泄露,搞得我花了一些時間去將同事寫的代碼認真地review了一遍)。


上一篇:榨干CPU

下一篇:vb.net Linq實戰

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 抚松县| 平塘县| 德钦县| 乌苏市| 中西区| 鄂州市| 天门市| 石城县| 体育| 章丘市| 老河口市| 同江市| 华蓥市| 咸宁市| 清河县| 麟游县| 宁津县| 祁东县| 龙海市| 陇西县| 鄯善县| 睢宁县| 南召县| 会宁县| 土默特右旗| 雷州市| 灌南县| 彩票| 武穴市| 富阳市| 新平| 思南县| 开封县| 广宗县| 东安县| 德安县| 黄浦区| 禹城市| 南靖县| 龙口市| 天镇县|