1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <sys/stat.h> #include <linux/aio_abi.h> #include <sys/syscall.h>
// 封装 io_setup 系统调用 static inline int my_io_setup(unsigned nr_events, io_context_t *ctxp) { return syscall(__NR_io_setup, nr_events, ctxp); }
// 封装 io_destroy 系统调用 static inline int my_io_destroy(io_context_t ctx) { return syscall(__NR_io_destroy, ctx); }
// 封装 io_submit 系统调用 static inline int my_io_submit(io_context_t ctx, long nr, struct iocb **iocbpp) { return syscall(__NR_io_submit, ctx, nr, iocbpp); }
// 辅助函数:初始化一个异步写入的 iocb 结构 void prep_pwrite(struct iocb *iocb, int fd, const void *buf, size_t count, __u64 offset) { memset(iocb, 0, sizeof(*iocb)); // 清零结构体 iocb->aio_lio_opcode = IOCB_CMD_PWRITE; // 设置操作类型为异步写 iocb->aio_fildes = fd; // 设置文件描述符 iocb->aio_buf = (__u64)(unsigned long)buf; // 设置缓冲区地址 iocb->aio_nbytes = count; // 设置写入字节数 iocb->aio_offset = offset; // 设置文件偏移量 iocb->aio_data = (__u64)(unsigned long)buf; // 设置用户数据 (这里用 buf 地址) }
int main() { const char *filename = "io_submit_test_file.txt"; const int num_writes = 3; const size_t chunk_size = 1024; int fd; io_context_t ctx = 0; // 必须初始化为 0 struct iocb iocbs[num_writes]; struct iocb *iocb_ptrs[num_writes]; char buffers[num_writes][chunk_size]; int ret, i;
printf("--- Demonstrating io_submit ---\n");
// 1. 初始化要写入的数据 for (i = 0; i < num_writes; ++i) { memset(buffers[i], 'A' + i, chunk_size); // Fill with 'A', 'B', 'C' }
// 2. 创建并打开文件 fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } printf("1. Opened/created file '%s' (fd=%d)\n", filename, fd);
// 3. 初始化异步 I/O 上下文 ret = my_io_setup(num_writes, &ctx); if (ret < 0) { perror("io_setup"); close(fd); exit(EXIT_FAILURE); } printf("2. Initialized AIO context (ctx_id=%llu)\n", (unsigned long long)ctx);
// 4. 准备 I/O 请求 (iocb) printf("3. Preparing %d asynchronous write requests...\n", num_writes); for (i = 0; i < num_writes; ++i) { prep_pwrite(&iocbs[i], fd, buffers[i], chunk_size, i * chunk_size); iocb_ptrs[i] = &iocbs[i]; printf(" Prepared write %d: offset=%zu, size=%zu, data='%c'...\n", i+1, i * chunk_size, chunk_size, 'A' + i); }
// 5. 提交 I/O 请求 printf("4. Submitting %d write requests using io_submit...\n", num_writes); ret = my_io_submit(ctx, num_writes, iocb_ptrs); if (ret != num_writes) { fprintf(stderr, " io_submit failed: submitted %d requests, expected %d\n", ret, num_writes); if (ret < 0) { perror(" io_submit error"); } else { printf(" Only the first %d requests were submitted successfully.\n", ret); } // 清理并退出 my_io_destroy(ctx); close(fd); unlink(filename); exit(EXIT_FAILURE); }
printf(" io_submit succeeded. All %d requests submitted.\n", ret);
// 6. 注意:此时写入操作可能仍在进行中,我们需要用 io_getevents 来等待完成 // 这个例子只演示提交,不等待完成。 printf("5. Note: io_submit returned immediately. The writes are happening in the background.\n"); printf(" To get the results, you need to call io_getevents().\n");
// 7. 清理资源 (在真实程序中,你应该在 io_getevents 确认完成后再关闭文件) printf("6. Cleaning up resources...\n"); my_io_destroy(ctx); printf(" Destroyed AIO context.\n"); close(fd); printf(" Closed file descriptor.\n"); unlink(filename); // 删除测试文件 printf(" Deleted test file '%s'.\n", filename);
printf("\n--- Summary ---\n"); printf("1. io_submit(ctx_id, nr, iocb_ptrs) submits 'nr' AIO requests to the context 'ctx_id'.\n"); printf("2. Each request is described by an 'iocb' struct, pointed to by elements in 'iocb_ptrs'.\n"); printf("3. It returns the number of requests successfully submitted (may be < nr on partial failure).\n"); printf("4. It returns immediately; the I/O happens asynchronously in the background.\n"); printf("5. Use io_getevents() afterwards to check for completion and get results.\n");
return 0; }
|