Search code examples
ciodisk

Disk write does not work with malloc in C


I did write to disk using C code.

First I tried with malloc and found that write did not work (write returned -1):

fd = open('/dev/sdb', O_DIRECT | O_SYNC | O_RDWR);
void *buff = malloc(512);
lseek(fd, 0, SEEK_SET);
write(fd, buff, 512);

Then I changed the second line with this and it worked:

void *buff;
posix_memalign(&buff,512,512);

However, when I changed the lseek offset to 1: lseek(fd, 1, SEEK_SET);, write did not work again.

First, why didn't malloc work?

Then, I know that in my case, posix_memalign guarantees that start address of memory alignment must be multiple of 512. But, should not memory alignment and write be a separate process? So why I could not write to any offset that I want?


Solution

  • From the Linux man page for open(2):

    The O_DIRECT flag may impose alignment restrictions on the length and address of user-space buffers and the file offset of I/Os.

    And:

    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 filesystem. Under Linux 2.6, alignment to 512-byte boundaries suffices.

    The meaning of O_DIRECT is to "try to minimize cache effects of the I/O to and from this file", and if I understand it correctly it means that the kernel should copy directly from the user-space buffer, thus perhaps requiring stricter alignment of the data.