Home > Coding > Direct I/O in Linux

Direct I/O in Linux

November 22nd, 2012

Correctly accessing a file or device with direct I/O is mainly about one thing: alignment. (1) When using lseek, device offset should be aligned to the boundary of a basic block unit, which is usually 512 bytes; (2) the buffer in main memory should be aligned as well; (3) request size cannot be a random number anymore, instead it should be multiples of the basic block size.

Without correct alignment, you will often get the “invalid argument” error. You can check the details using system tool “strace”.

The following is a program that demonstrates an example of doing direct I/O. Notice the use of “posix_memalign” to align in-memory buffer, and the request size is 1024 (multiples of 512). I didn’t use “lseek” in this program, but keep in mind, the offset of lseek can only be multiples of the basic block size (in my case 512 bytes) as well.

  1. #define _GNU_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <errno.h>
  8. #include <string.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11.  
  12. extern int errno;
  13. int main()
  14. {
  15.  int fd, ret;
  16.  int count = 1024;
  17.  char *buf;
  18.  
  19.  if(posix_memalign((void **)&buf, 512, count) != 0){
  20.         printf("[Failed to align\n", strerror(errno));
  21.         return;
  22.  }
  23.  
  24.  fd = open("/dev/sdb", O_RDONLY | O_DIRECT);
  25.  if (fd < 0){
  26.    printf("[Failed to open] %s\n", strerror(errno));
  27.    return 1;
  28.  }
  29.  
  30.  
  31.  if ((ret = read(fd, buf, count)) < 0) {
  32.    printf("[Failed to read] %s\n", strerror(errno));
  33.    return 1;
  34.  }
  35.  
  36.  close(fd);
  37.  return 0;
  38. }

Coding

  1. No comments yet.
  1. No trackbacks yet.