Created
February 17, 2026 22:05
-
-
Save redixhumayun/8f402d30ffc8437e043394b9c003698b to your computer and use it in GitHub Desktop.
Comparison of two C files to verify the requirement for aligned structs for direct IO
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define _GNU_SOURCE | |
| #include <fcntl.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <errno.h> | |
| #include <stdint.h> | |
| #define BUF_SIZE 4096 | |
| struct __attribute__((packed)) Header { | |
| char tag; // 1 byte — forces misalignment of subsequent fields | |
| unsigned long id; // 8 bytes, but at offset 1 due to packing | |
| char data[BUF_SIZE - 9]; | |
| }; | |
| int main() { | |
| // malloc returns ~16-byte aligned memory, NOT 4096-aligned | |
| struct Header *buf = malloc(sizeof(struct Header)); | |
| if (!buf) { perror("malloc"); return 1; } | |
| memset(buf, 0, sizeof(*buf)); | |
| buf->tag = 'X'; | |
| buf->id = 42; | |
| strcpy(buf->data, "hello direct io"); | |
| printf("buffer address: %p\n", (void *)buf); | |
| printf("buffer size: %zu\n", sizeof(*buf)); | |
| printf("aligned to 512? %s\n", ((uintptr_t)buf % 512 == 0) ? "yes" : "no"); | |
| printf("aligned to 4096? %s\n", ((uintptr_t)buf % 4096 == 0) ? "yes" : "no"); | |
| // open with O_DIRECT | |
| int fd = open("/tmp/direct_io_test.dat", O_CREAT | O_WRONLY | O_DIRECT, 0644); | |
| if (fd < 0) { perror("open"); free(buf); return 1; } | |
| ssize_t written = write(fd, buf, BUF_SIZE); | |
| if (written < 0) { | |
| printf("write failed: %s (errno=%d)\n", strerror(errno), errno); | |
| } else { | |
| printf("write succeeded: %zd bytes\n", written); | |
| } | |
| close(fd); | |
| free(buf); | |
| return 0; | |
| } | |
| /** | |
| * Second half of the program | |
| */ | |
| #define _GNU_SOURCE | |
| #include <fcntl.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <errno.h> | |
| #include <stdint.h> | |
| #define BUF_SIZE 4096 | |
| #define ALIGNMENT 4096 | |
| struct __attribute__((packed)) Header { | |
| char tag; | |
| unsigned long id; | |
| char data[BUF_SIZE - 9]; | |
| }; | |
| int main() { | |
| struct Header *buf = NULL; | |
| int ret = posix_memalign((void **)&buf, ALIGNMENT, sizeof(struct Header)); | |
| if (ret != 0) { fprintf(stderr, "posix_memalign failed: %s\n", strerror(ret)); return 1; } | |
| memset(buf, 0, sizeof(*buf)); | |
| buf->tag = 'X'; | |
| buf->id = 42; | |
| strcpy(buf->data, "hello direct io"); | |
| printf("buffer address: %p\n", (void *)buf); | |
| printf("buffer size: %zu\n", sizeof(*buf)); | |
| printf("aligned to 512? %s\n", ((uintptr_t)buf % 512 == 0) ? "yes" : "no"); | |
| printf("aligned to 4096? %s\n", ((uintptr_t)buf % 4096 == 0) ? "yes" : "no"); | |
| int fd = open("/tmp/direct_io_test_aligned.dat", O_CREAT | O_WRONLY | O_DIRECT, 0644); | |
| if (fd < 0) { perror("open"); free(buf); return 1; } | |
| ssize_t written = write(fd, buf, BUF_SIZE); | |
| if (written < 0) { | |
| printf("write failed: %s (errno=%d)\n", strerror(errno), errno); | |
| } else { | |
| printf("write succeeded: %zd bytes\n", written); | |
| } | |
| close(fd); | |
| free(buf); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment