[20181214]open file using O_DIRECT.txt--//因為一個測試需要,需要寫一個測試小例子,驗證使用O_DIRECT打開文件每次都是從磁碟讀取.--//沒想到浪費1個上午時間,C語言不是自己的擅長.#include <stdio.h>#include <stdlib. ...
[20181214]open file using O_DIRECT.txt
--//因為一個測試需要,需要寫一個測試小例子,驗證使用O_DIRECT打開文件每次都是從磁碟讀取.
--//沒想到浪費1個上午時間,C語言不是自己的擅長.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
//#define __USE_GNU 1
#include <fcntl.h>
int main(void)
{
void *realbuff ;
int handle;
int bytes ;
int pagesize;
int nTemp ;
pagesize = getpagesize();
// printf("%d\n",pagesize);
realbuff = valloc( 1024000 );
nTemp = posix_memalign(&realbuff, pagesize, 1024000);
if (0!=nTemp)
{
perror("posix_memalign error");
return 1;
}
handle=open("test.bin",O_RDONLY|O_DIRECT);
if(handle==-1)
{
printf("ErrorOpeningFile\n");
exit(1);
}
while ( (bytes=read(handle,realbuff,1024000))>0 )
{
sleep(1);
printf("Read:%d bytes read.\n",bytes);
}
return 0 ;
}
--//自己的問題在於不能使用malloc分配緩存.而應該使用valloc分配,不然在posix_memalign這步就報錯,使用valloc才能對齊pagesize.
--//順便說一下getpagesize()我的測試返回是4096.我使用gcc版本:
$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-54)
$ dd if=/dev/zero of=test.bin bs=1024000 count=10
10+0 records in
10+0 records out
10240000 bytes (10 MB) copied, 0.0343163 seconds, 298 MB/s
$ gcc -D_GNU_SOURCE direct_test.c -o direct_test
--//第2個問題就是使用O_DIRECT打開文件句柄,必須定義__USE_GNU 1.或者編譯時加-D_GNU_SOURCE參數,否則找不到O_DIRECT的巨集定義.
--//實際上這個應該是最先遇到的問題.
$ ./direct_test
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
Read:1024000 bytes read.
# dstat -t -d -D cciss/c0d0p2,cciss/c0d0p6,total
-----time----- dsk/cciss/c-dsk/cciss/c--dsk/total-
date/time | read writ: read writ: read writ
14-12 15:45:13|1213B 7936B: 11k 65k: 24k 146k
....
14-12 15:45:16| 36k 0 : 0 0 : 72k 0
14-12 15:45:17|1000k 0 : 0 0 :2000k 0
14-12 15:45:18|1000k 0 : 0 0 :2000k 0
14-12 15:45:19|1004k 0 : 0 0 :2008k 0
14-12 15:45:20|1000k 0 : 0 0 :2000k 0
14-12 15:45:21|1000k 0 : 0 0 :2000k 0
14-12 15:45:22|1016k 2564k: 0 0 :2032k 5128k
14-12 15:45:23|1000k 0 : 0 0 :2000k 0
14-12 15:45:24|1000k 0 : 0 0 :2000k 0
14-12 15:45:25|1000k 0 : 0 0 :2000k 0
14-12 15:45:26|1000k 0 : 0 0 :2000k 0
14-12 15:45:27| 0 0 : 0 0 : 0 0
--//註:可以發現每秒從磁碟/dev/cciss/c0d0p2讀取1000K.繞過os文件緩存.另外這個dstat版本有問題,total的記數會加倍.
# man open
...
O_DIRECT
Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance,
but it is useful in special situations, such as when applications do their own caching. File I/O is done
directly to/from user space buffers. The I/O is synchronous, i.e., at the completion of a read(2) or
write(2), data is guaranteed to have been transferred. 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. Under
Linux 2.6 alignment must fit the block size of the device.
--//也就是這樣讀取效率低下,每次都是從磁碟讀取.除非applications do their own caching.
--//順便說一下國內開發有許多相關討論的帖子,查詢open O_DIRECT就能找到.