[20181214]open file using O_DIRECT.txt

lfree發表於2018-12-14

[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就能找到.


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-2285296/,如需轉載,請註明出處,否則將追究法律責任。

相關文章