Datei auslesen mit O_DIRECT



  • Hallo zusammen,

    ich nutze gerade Ubuntu 11.04 mit ext4.

    Jetzt muss ich aber eine Datei mit dem O_DIRECT Flag öffnen und diese auslesen. Allerdiungs funktioniet das nicht.

    Wenn ich nun die Datei auslesen will hat danach errno immer den Wert 22, also EINVAl. Anscheinend gibt es die Option O_DIRECT nicht. Aber wie kann ich diese aktivieren?

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <errno.h>
    
    int file_descriptor;
    int byte_count;
    
    char path[] = {"test.txt"};
    char buffer[1024];
    
    file_descriptor = open(path, O_DIRECT, O_RDONLY);
    
    //bis hier ist noch alle OK
    
    byte_count = read(file_descriptor, buffer, 1024);
    
    //ab hier kommt der Fehler
    
    if(errno == EINVAL) {
    
    //hier steht noch Code
    }
    


  • open erwartet die Flags als zweiten Parameter, der dritte (optionale) Parameter ist für die Zugriffsrechte beim Erzeugen einer Datei. Mehrere Flags verknüpfst Du mit dem boolschen Oder "|".



  • Ich ahbe mal folgende Variante ausprobiert:

    //...
    file_descriptor = open(path, O_DIRECT |O_RDONLY);
    
    //...
    

    Allerdings bekomme ich hier den selben Fehler.



  • Du musst auf das richtige Alignment achten.

    http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html

    The O_DIRECT flag may impose alignment restrictions on the length and address
    of userspace buffers and the file offset of I/Os. In Linux alignment
    restrictions vary by file system and kernel version and might be absent
    entirely. However there is currently no file system-independent interface for
    an application to discover these restrictions for a given file or file system.
    Some file systems provide their own interfaces for doing so, for example the
    XFS_IOC_DIOINFO operation in xfsctl(3).

    Under Linux 2.4, transfer sizes, and the alignment of the user buffer and the
    file offset must all be multiples of the logical block size of the file
    system. Under Linux 2.6, alignment to 512-byte boundaries suffices.

    siehe http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-04/3074.html



  • Ok, ich habe meinen Speicher mal anders allociert, allerdings verstehe ich noch nicht warum man hier ein alignment eintragen muss, denn die Größe gebe ich ja im dritten Parameter von posix_memalign an.

    //...
    char *buf;
    
    posix_memalign((void**)&buf, 1024, 4096*sizeof(char));
    
    byte_count = read(file_descriptor, buffer, 1024);
    
    //...
    


  • Alignment hat nichts mit der Größe zu tun. Es sagt nur, dass die Adresse ein Vielfaches des Alignments ist.

    The address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of sizeof(void *).

    http://www.kernel.org/doc/man-pages/online/pages/man3/posix_memalign.3.html



  • Aber was ist das alignment genau?


Log in to reply