#define _FILE_OFFSET_BITS 64 //訪(fǎng)問(wèn)大磁盤(pán)
#define _GNU_SOURCE //定義O_DIRECT
#define _GNU_SOURCE //定義O_DIRECT
#i nclude <fcntl.h>
open的O_DIRECT選項- -
一個(gè)客戶(hù)的技術(shù)支持。
問(wèn)題的背景是他們希望系統掉電時(shí),損失最小。而用O_DIRECT選項,則文件buffer/cache的機制造成的數據丟失將最小??墒乾F在問(wèn)題是DIRECT open一個(gè)文件沒(méi)問(wèn)題,讀/寫(xiě)不正確。
察看open的man page,注意到關(guān)于DIRECT選項的一些說(shuō)明:
Under Linux 2.4, transfer sizes, and the alignment of user
buffer and file offset must all be multiples of the logical block size of the file system....
大概是說(shuō),DIRECT的前提必須是buffer地址/傳送數據大小都要求"文件系統邏輯塊"大小對齊。也就是說(shuō),如果我的文件系統邏輯塊是4096byte,那么buffer的地址必須是4096的整數倍,每次讀寫(xiě)的字節數、offset也是這樣。
于是作了一下嘗試,我的文件系統邏輯塊是4096(大多數都是這樣),用這個(gè)命令可以查到:
#dumpe2fs /dev/sda6|grep -i "block size" |
現在主要是解決buffer的地址4096對齊的問(wèn)題,用gcc的編譯選項定義全局變量buffer:
typedef char _aligned_char __attribute__ ((aligned (8192))); |
這樣,全局定義的buffer就會(huì )按照4096對齊分配了,nm/objdump都可以看到,也可以在程序中打出來(lái)看看:
printf("buffer=%x\n",buffer); |
這回寫(xiě)一下:
len=write(fd,buffer,4096); |
len的返回值是4096,證明修改是正確的,當然,還要驗證一下:
去掉buffer的align選項,編譯運行,perror write的結果:
len=write(fd,buffer,4096); |
出現:
erro: Invalid argument |
證明align起作用了。
問(wèn)題倒是臨時(shí)解決了,不過(guò)還是有問(wèn)題,google O_DIRECT,很多說(shuō)法不太一樣,有的說(shuō)要page size align,有的說(shuō)logical block align,現在沒(méi)有一個(gè)塊大小是1024的文件系統,沒(méi)法試,不過(guò)這也沒(méi)什么,就按二者大的來(lái)吧:-)。

