Linux下利用O_DIRECT標誌繞過VFS cache Tweet

來源:互聯網
上載者:User

轉載:http://passer-byb.com/blog/85.html

這個問題折騰了我有一個星期了,因為最近一直在搞有關磁碟的I/O的測試,因此需要繞過或者關閉VFS的cache直接對磁碟進行讀寫。Google過之後發現基本上想要關閉cache是不可能的,只有想辦法繞過了。於是很自然的想到了write()和read()這兩個東西,可是當時並沒意識到buffer跟cache並不是一個東西。write()跟read()雖然叫直接I/O但事實上他們只是繞過了buffer,也就是說在讀入跟輸出的時候不進行任何的緩衝,但VFS本身的cache仍然存在,VFS仍然會選擇在合適的時候將cache的資料寫入磁碟。
於是找了很多方法,有的是通過drop cache的方法,就是"echo 1 > /proc/sys/vm/drop_caches"這樣的方法,不過這種方法只能清除一次cache,讀寫一次,很是麻煩。於是果斷放棄了這種不靠譜的方法。
後來想到了APUE上沒有提到的一個O_DIRECT flag(因為APUE講的是UNIX編程,當然沒必要照顧到GNU Linux特有的東西)。具體怎麼用呢,下面就來說說。
首先在檔案頭需要定義

#define _GNU_SOURCE

然後,這個東西用在open()獲得檔案描述符時所填寫的第二個參數,也就是open(path,flag,mode)的第二個參數。比如你要以寫方式建立一個路徑為"/home/user/test.test"新檔案,並且要直接I/O繞過cache,就可以這樣寫:

int fd=open("/home/user/test.test",O_WRONLY|O_CREAT|O_DIRECT,S_IRUSR|S_IWUSR);

之後在你需要read()或者write()的時候,傳入的buffer的首地址,以及buffer的大小都必須跟檔案系統的page size對齊。這個page size可以通過getpagesize()獲得。所以這裡要用到一個我的笨辦法:

int buffersize = getpagesize()*page_num;
int pagesize=getpagesize();
char * t_buf = (char *) malloc(buffersize+pagesize);
char * buffer = (char *)(((unsigned int)buffersize+pagesize-1)/pagesize*pagesize);

之後你就可以用這個buffer來read()或者write()了。如:

read(fd,buffer,buffersize);

要注意的是這裡的buffersize必須是頁大小的整數倍,並且buffer指向的地址也必須是頁大小的整數倍。用上面的簡單計算就可以得到滿足條件的buffer。之後的I/O便是完全繞過cache的direct I/O了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.