io_cancel系统调用及示例

io_cancel 函数详解

  1. 函数介绍

io_cancel 是Linux传统异步I/O (AIO) 系统调用,用于取消先前提交但尚未完成的异步I/O操作。它是AIO框架的重要组成部分,允许应用程序在必要时取消正在进行的异步操作,提供更灵活的I/O控制能力。

  1. 函数原型
1
2
3
#include <linux/aio_abi.h>
int io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result);

  1. 功能

io_cancel 尝试取消指定的异步I/O操作。如果操作仍在排队或尚未开始执行,则可以成功取消;如果操作已经开始执行或已经完成,则取消可能失败。成功取消的操作会返回一个带有ECANCELED错误码的完成事件。

  1. 参数
  • aio_context_t ctx_id: AIO上下文ID(由io_setup创建)

  • *struct iocb iocb: 要取消的异步I/O控制块指针

  • *struct io_event result: 用于存储取消结果的事件结构指针

  1. 返回值
  • 成功: 返回0

  • 失败: 返回负的错误码

  1. 相似函数,或关联函数
  • io_setup: 初始化AIO上下文

  • io_destroy: 销毁AIO上下文

  • io_submit: 提交异步I/O操作

  • io_getevents: 获取完成的异步I/O事件

  • io_pgetevents: 带信号处理的事件获取

  1. 示例代码

示例1:基础io_cancel使用

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>

/**
* 系统调用包装函数
*/
static inline int io_setup(unsigned nr_events, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr_events, ctxp);
}

static inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}

static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}

static inline int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result) {
return syscall(__NR_io_cancel, ctx, iocb, result);
}

static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);
}

/**
* 演示基础io_cancel使用方法
*/
int demo_io_cancel_basic() {
aio_context_t ctx;
struct iocb iocb;
struct io_event result;
int fd;
int ret;

printf("=== 基础io_cancel使用示例 ===\n");

// 初始化AIO上下文
printf("1. 初始化AIO上下文:\n");
ctx = 0;
ret = io_setup(128, &ctx);
if (ret < 0) {
printf(" 初始化AIO上下文失败: %s\n", strerror(-ret));
return -1;
}
printf(" ✓ AIO上下文初始化成功\n");
printf(" 上下文ID: %llu\n", (unsigned long long)ctx);

// 创建测试文件
printf("\n2. 创建测试文件:\n");
const char *filename = "aio_cancel_test.txt";
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
perror(" 创建测试文件失败");
io_destroy(ctx);
return -1;
}
printf(" ✓ 测试文件创建成功: %s\n", filename);

// 准备异步写入操作
printf("\n3. 准备异步写入操作:\n");
char *test_data = "This is test data for AIO cancel operation.\n";
size_t data_size = strlen(test_data);

// 初始化iocb结构
memset(&iocb, 0, sizeof(iocb));
iocb.aio_data = 12345; // 用户数据
iocb.aio_key = 0;
iocb.aio_rw_flags = 0;
iocb.aio_lio_opcode = IOCB_CMD_PWRITE; // 异步写入
iocb.aio_reqprio = 0;
iocb.aio_fildes = fd;
iocb.aio_buf = (uint64_t)(uintptr_t)test_data;
iocb.aio_nbytes = data_size;
iocb.aio_offset = 0;
iocb.aio_flags = 0;
iocb.aio_resfd = 0;

printf(" 准备异步写入操作:\n");
printf(" 文件描述符: %d\n", fd);
printf(" 数据大小: %zu 字节\n", data_size);
printf(" 用户数据: %llu\n", (unsigned long long)iocb.aio_data);

// 提交异步操作
printf("\n4. 提交异步操作:\n");
struct iocb *iocbs&#91;1] = {&iocb};
ret = io_submit(ctx, 1, iocbs);
if (ret != 1) {
printf(" 提交异步操作失败: %s\n", strerror(-ret));
close(fd);
unlink(filename);
io_destroy(ctx);
return -1;
}
printf(" ✓ 异步操作提交成功\n");

// 立即尝试取消操作
printf("\n5. 立即尝试取消操作:\n");
ret = io_cancel(ctx, &iocb, &result);
if (ret == 0) {
printf(" ✓ 操作取消成功\n");
printf(" 取消结果:\n");
printf(" 用户数据: %llu\n", (unsigned long long)result.data);
printf(" 结果: %ld\n", result.res);
printf(" 结果2: %ld\n", result.res2);
if (result.res == -ECANCELED) {
printf(" 状态: 操作已取消 (ECANCELED)\n");
}
} else if (ret == -EAGAIN) {
printf(" ℹ 操作无法取消 (可能已开始执行或已完成)\n");

// 等待操作完成
printf(" 等待操作完成...\n");
struct io_event events&#91;1];
ret = io_getevents(ctx, 1, 1, events, NULL);
if (ret > 0) {
printf(" ✓ 操作完成\n");
printf(" 用户数据: %llu\n", (unsigned long long)events&#91;0].data);
printf(" 结果: %ld 字节\n", events&#91;0].res);
}
} else {
printf(" ✗ 取消操作失败: %s\n", strerror(-ret));
}

// 演示延时取消
printf("\n6. 演示延时取消:\n");

// 创建一个更大的写入操作
char *large_data = malloc(1024 * 1024); // 1MB数据
if (large_data) {
// 填充数据
for (int i = 0; i < 1024 * 1024; i++) {
large_data&#91;i] = 'A' + (i % 26);
}

// 准备新的iocb
struct iocb large_iocb;
memset(&large_iocb, 0, sizeof(large_iocb));
large_iocb.aio_data = 54321;
large_iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
large_iocb.aio_fildes = fd;
large_iocb.aio_buf = (uint64_t)(uintptr_t)large_data;
large_iocb.aio_nbytes = 1024 * 1024;
large_iocb.aio_offset = data_size; // 在之前数据之后

printf(" 准备大块数据写入操作 (1MB)\n");

struct iocb *large_iocbs&#91;1] = {&large_iocb};
ret = io_submit(ctx, 1, large_iocbs);
if (ret == 1) {
printf(" ✓ 大块数据写入操作提交成功\n");

// 短暂延迟后尝试取消
printf(" 等待100ms后尝试取消...\n");
usleep(100000); // 100ms

struct io_event cancel_result;
ret = io_cancel(ctx, &large_iocb, &cancel_result);
if (ret == 0) {
printf(" ✓ 大块数据写入操作取消成功\n");
} else if (ret == -EAGAIN) {
printf(" ℹ 大块数据写入操作无法取消\n");

// 等待操作完成
struct io_event events&#91;1];
int wait_ret = io_getevents(ctx, 1, 1, events, NULL);
if (wait_ret > 0) {
printf(" ✓ 大块数据写入完成: %ld 字节\n", events&#91;0].res);
}
} else {
printf(" ✗ 取消大块数据写入失败: %s\n", strerror(-ret));
}
}

free(large_data);
}

// 清理资源
printf("\n7. 清理资源:\n");
close(fd);
unlink(filename);
io_destroy(ctx);
printf(" ✓ 资源清理完成\n");

return 0;
}

int main() {
return demo_io_cancel_basic();
}

示例2:批量操作取消

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>

/**
* 系统调用包装函数
*/
static inline int io_setup(unsigned nr_events, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr_events, ctxp);
}

static inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}

static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}

static inline int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result) {
return syscall(__NR_io_cancel, ctx, iocb, result);
}

static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);
}

/**
* 批量操作取消演示
*/
int demo_batch_cancel() {
aio_context_t ctx;
const int batch_size = 8;
struct iocb iocbs&#91;batch_size];
struct io_event results&#91;batch_size];
int fd;
int ret;
char *test_files&#91;batch_size];

printf("=== 批量操作取消演示 ===\n");

// 初始化AIO上下文
printf("1. 初始化AIO上下文:\n");
ctx = 0;
ret = io_setup(128, &ctx);
if (ret < 0) {
printf(" 初始化AIO上下文失败: %s\n", strerror(-ret));
return -1;
}
printf(" ✓ AIO上下文初始化成功\n");

// 创建测试文件
printf("\n2. 创建测试文件:\n");
for (int i = 0; i < batch_size; i++) {
char filename&#91;32];
snprintf(filename, sizeof(filename), "batch_cancel_%d.txt", i);
test_files&#91;i] = strdup(filename);

fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd != -1) {
// 写入一些初始数据使文件不为空
char initial_data&#91;256];
memset(initial_data, 'A' + i, sizeof(initial_data) - 1);
initial_data&#91;sizeof(initial_data) - 1] = '\0';
write(fd, initial_data, sizeof(initial_data) - 1);
close(fd);
printf(" 创建测试文件 %d: %s\n", i, filename);
}
}

// 准备批量异步读取操作
printf("\n3. 准备批量异步读取操作:\n");
struct iocb *iocb_ptrs&#91;batch_size];

for (int i = 0; i < batch_size; i++) {
fd = open(test_files&#91;i], O_RDONLY);
if (fd == -1) {
printf(" 打开文件 %s 失败\n", test_files&#91;i]);
continue;
}

// 初始化iocb
memset(&iocbs&#91;i], 0, sizeof(iocbs&#91;i]));
iocbs&#91;i].aio_data = i + 1; // 使用索引作为用户数据
iocbs&#91;i].aio_lio_opcode = IOCB_CMD_PREAD;
iocbs&#91;i].aio_fildes = fd;

// 分配读取缓冲区
char *read_buffer = malloc(1024);
if (read_buffer) {
iocbs&#91;i].aio_buf = (uint64_t)(uintptr_t)read_buffer;
iocbs&#91;i].aio_nbytes = 1024;
iocbs&#91;i].aio_offset = 0;
}

iocb_ptrs&#91;i] = &iocbs&#91;i];
printf(" 准备读取操作 %d: 文件 %s\n", i + 1, test_files&#91;i]);
}

// 提交批量操作
printf("\n4. 提交批量异步操作:\n");
ret = io_submit(ctx, batch_size, iocb_ptrs);
if (ret < 0) {
printf(" 提交批量操作失败: %s\n", strerror(-ret));
goto cleanup;
}
printf(" ✓ 成功提交 %d 个异步操作\n", ret);

// 演示部分取消
printf("\n5. 演示部分操作取消:\n");
int cancel_count = 0;

for (int i = 0; i < batch_size; i += 2) { // 取消偶数索引的操作
ret = io_cancel(ctx, &iocbs&#91;i], &results&#91;cancel_count]);
if (ret == 0) {
printf(" ✓ 操作 %d 取消成功\n", (int)iocbs&#91;i].aio_data);
cancel_count++;
} else if (ret == -EAGAIN) {
printf(" ℹ 操作 %d 无法取消 (可能已开始执行)\n", (int)iocbs&#91;i].aio_data);
} else {
printf(" ✗ 操作 %d 取消失败: %s\n", (int)iocbs&#91;i].aio_data, strerror(-ret));
}
}

printf(" 总共尝试取消 %d 个操作\n", cancel_count);

// 等待剩余操作完成
printf("\n6. 等待剩余操作完成:\n");
struct io_event completed_events&#91;batch_size];
int completed_count = 0;

// 等待最多5秒
struct timespec timeout = {5, 0};
ret = io_getevents(ctx, 1, batch_size, completed_events, &timeout);
if (ret > 0) {
printf(" ✓ 收到 %d 个完成事件\n", ret);
completed_count = ret;

for (int i = 0; i < ret; i++) {
printf(" 操作 %llu 完成: %ld 字节\n",
(unsigned long long)completed_events&#91;i].data,
completed_events&#91;i].res);
}
} else if (ret == 0) {
printf(" ⚠ 超时,没有收到完成事件\n");
} else {
printf(" ✗ 等待完成事件失败: %s\n", strerror(-ret));
}

// 显示取消结果
printf("\n7. 取消结果统计:\n");
printf(" 尝试取消的操作数: %d\n", cancel_count);
printf(" 完成的操作数: %d\n", completed_count);
printf(" 总操作数: %d\n", batch_size);

// 清理资源
cleanup:
printf("\n8. 清理资源:\n");

// 关闭文件描述符和释放缓冲区
for (int i = 0; i < batch_size; i++) {
if (iocbs&#91;i].aio_fildes > 0) {
close(iocbs&#91;i].aio_fildes);
}
if (iocbs&#91;i].aio_buf) {
free((void*)(uintptr_t)iocbs&#91;i].aio_buf);
}
if (test_files&#91;i]) {
unlink(test_files&#91;i]);
free(test_files&#91;i]);
}
}

io_destroy(ctx);
printf(" ✓ 所有资源清理完成\n");

return 0;
}

int main() {
return demo_batch_cancel();
}

示例3:超时取消机制

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>

/**
* 系统调用包装函数
*/
static inline int io_setup(unsigned nr_events, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr_events, ctxp);
}

static inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}

static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}

static inline int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result) {
return syscall(__NR_io_cancel, ctx, iocb, result);
}

static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);
}

/**
* 超时取消上下文
*/
typedef struct {
aio_context_t ctx;
struct iocb *iocb;
int is_completed;
int is_cancelled;
time_t start_time;
int timeout_seconds;
} timeout_cancel_ctx_t;

/**
* 超时处理函数
*/
void timeout_handler(int sig) {
printf("收到超时信号\n");
}

/**
* 演示超时取消机制
*/
int demo_timeout_cancel_mechanism() {
aio_context_t ctx;
struct iocb iocb;
struct io_event result;
int fd;
int ret;

printf("=== 超时取消机制演示 ===\n");

// 初始化AIO上下文
printf("1. 初始化AIO上下文:\n");
ctx = 0;
ret = io_setup(64, &ctx);
if (ret < 0) {
printf(" 初始化AIO上下文失败: %s\n", strerror(-ret));
return -1;
}
printf(" ✓ AIO上下文初始化成功\n");

// 创建测试文件
printf("\n2. 创建测试文件:\n");
const char *filename = "timeout_test.txt";
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
perror(" 创建测试文件失败");
io_destroy(ctx);
return -1;
}

// 写入大量数据
char *large_data = malloc(10 * 1024 * 1024); // 10MB数据
if (large_data) {
for (int i = 0; i < 10 * 1024 * 1024; i++) {
large_data&#91;i] = 'A' + (i % 26);
}
write(fd, large_data, 10 * 1024 * 1024);
}
close(fd);

printf(" ✓ 创建了10MB测试文件: %s\n", filename);

// 重新打开文件进行读取
fd = open(filename, O_RDONLY);
if (fd == -1) {
perror(" 打开测试文件失败");
io_destroy(ctx);
unlink(filename);
return -1;
}

// 准备长时间读取操作
printf("\n3. 准备长时间读取操作:\n");
char *read_buffer = malloc(5 * 1024 * 1024); // 5MB缓冲区
if (!read_buffer) {
perror(" 分配读取缓冲区失败");
close(fd);
io_destroy(ctx);
unlink(filename);
return -1;
}

// 初始化iocb
memset(&iocb, 0, sizeof(iocb));
iocb.aio_data = 99999;
iocb.aio_lio_opcode = IOCB_CMD_PREAD;
iocb.aio_fildes = fd;
iocb.aio_buf = (uint64_t)(uintptr_t)read_buffer;
iocb.aio_nbytes = 5 * 1024 * 1024; // 读取5MB
iocb.aio_offset = 0;

printf(" 准备读取5MB数据\n");

// 提交异步读取操作
struct iocb *iocbs&#91;1] = {&iocb};
ret = io_submit(ctx, 1, iocbs);
if (ret != 1) {
printf(" 提交异步读取操作失败: %s\n", strerror(-ret));
free(read_buffer);
close(fd);
io_destroy(ctx);
unlink(filename);
return -1;
}
printf(" ✓ 异步读取操作提交成功\n");

// 设置超时处理
printf("\n4. 设置超时处理:\n");
time_t start_time = time(NULL);
const int timeout_seconds = 3;

printf(" 设置超时时间: %d 秒\n", timeout_seconds);

// 等待操作完成或超时
printf("\n5. 等待操作完成或超时:\n");
struct io_event events&#91;1];
struct timespec timeout = {1, 0}; // 1秒超时

int operation_completed = 0;
int cancel_attempted = 0;

while (difftime(time(NULL), start_time) < timeout_seconds) {
ret = io_getevents(ctx, 0, 1, events, &timeout);
if (ret > 0) {
printf(" ✓ 操作在超时前完成\n");
printf(" 读取字节数: %ld\n", events&#91;0].res);
operation_completed = 1;
break;
} else if (ret == 0) {
printf(" 操作仍在进行中...\n");

// 每秒检查一次是否需要取消
if (!cancel_attempted && difftime(time(NULL), start_time) >= 2) {
printf(" 2秒后尝试取消操作\n");
struct io_event cancel_result;
ret = io_cancel(ctx, &iocb, &cancel_result);
if (ret == 0) {
printf(" ✓ 操作取消成功\n");
cancel_attempted = 1;
break;
} else if (ret == -EAGAIN) {
printf(" ℹ 操作无法取消\n");
cancel_attempted = 1;
} else {
printf(" ✗ 取消操作失败: %s\n", strerror(-ret));
cancel_attempted = 1;
}
}
} else {
printf(" ✗ 等待事件失败: %s\n", strerror(-ret));
break;
}
}

// 超时后的处理
if (!operation_completed && !cancel_attempted) {
printf("\n6. 超时处理:\n");
printf(" 操作超时 (%d 秒)\n", timeout_seconds);

// 强制取消操作
printf(" 强制取消操作...\n");
struct io_event cancel_result;
ret = io_cancel(ctx, &iocb, &cancel_result);
if (ret == 0) {
printf(" ✓ 操作取消成功\n");
} else if (ret == -EAGAIN) {
printf(" ℹ 操作无法取消\n");
} else {
printf(" ✗ 取消操作失败: %s\n", strerror(-ret));
}
}

// 等待最终结果
printf("\n7. 等待最终结果:\n");
timeout.tv_sec = 2; // 2秒超时
timeout.tv_nsec = 0;

ret = io_getevents(ctx, 0, 1, events, &timeout);
if (ret > 0) {
printf(" 最终结果:\n");
printf(" 用户数据: %llu\n", (unsigned long long)events&#91;0].data);
printf(" 结果: %ld\n", events&#91;0].res);
if (events&#91;0].res == -ECANCELED) {
printf(" 状态: 操作已取消\n");
} else if (events&#91;0].res < 0) {
printf(" 错误: %s\n", strerror(-events&#91;0].res));
} else {
printf(" 成功读取: %ld 字节\n", events&#91;0].res);
}
} else if (ret == 0) {
printf(" 超时,无结果返回\n");
} else {
printf(" 等待结果失败: %s\n", strerror(-ret));
}

// 清理资源
printf("\n8. 清理资源:\n");
free(read_buffer);
close(fd);
unlink(filename);
io_destroy(ctx);
printf(" ✓ 资源清理完成\n");

return 0;
}

int main() {
return demo_timeout_cancel_mechanism();
}

示例4:条件取消策略

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>

/**
* 系统调用包装函数
*/
static inline int io_setup(unsigned nr_events, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr_events, ctxp);
}

static inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}

static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}

static inline int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result) {
return syscall(__NR_io_cancel, ctx, iocb, result);
}

static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);
}

/**
* 取消策略枚举
*/
typedef enum {
CANCEL_STRATEGY_IMMEDIATE, // 立即取消
CANCEL_STRATEGY_TIMEOUT, // 超时取消
CANCEL_STRATEGY_CONDITIONAL, // 条件取消
CANCEL_STRATEGY_NEVER // 从不取消
} cancel_strategy_t;

/**
* 操作上下文
*/
typedef struct {
struct iocb iocb;
int is_submitted;
int is_completed;
int is_cancelled;
time_t submit_time;
cancel_strategy_t strategy;
int timeout_seconds;
int condition_value;
} operation_context_t;

/**
* 条件取消检查函数
*/
int check_cancel_condition(operation_context_t *ctx) {
switch (ctx->strategy) {
case CANCEL_STRATEGY_IMMEDIATE:
return 1; // 立即取消

case CANCEL_STRATEGY_TIMEOUT:
if (difftime(time(NULL), ctx->submit_time) > ctx->timeout_seconds) {
printf(" 操作超时,触发取消\n");
return 1;
}
return 0;

case CANCEL_STRATEGY_CONDITIONAL:
// 模拟条件检查
if (ctx->condition_value > 100) {
printf(" 条件满足,触发取消\n");
return 1;
}
return 0;

case CANCEL_STRATEGY_NEVER:
default:
return 0;
}
}

/**
* 演示条件取消策略
*/
int demo_conditional_cancel_strategy() {
aio_context_t ctx;
operation_context_t operations&#91;5];
int fd;
int ret;

printf("=== 条件取消策略演示 ===\n");

// 初始化AIO上下文
printf("1. 初始化AIO上下文:\n");
ctx = 0;
ret = io_setup(64, &ctx);
if (ret < 0) {
printf(" 初始化AIO上下文失败: %s\n", strerror(-ret));
return -1;
}
printf(" ✓ AIO上下文初始化成功\n");

// 创建测试文件
printf("\n2. 创建测试文件:\n");
const char *filename = "conditional_cancel_test.txt";
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
perror(" 创建测试文件失败");
io_destroy(ctx);
return -1;
}

// 写入测试数据
char *test_data = malloc(1024 * 1024); // 1MB数据
if (test_data) {
for (int i = 0; i < 1024 * 1024; i++) {
test_data&#91;i] = 'A' + (i % 26);
}
write(fd, test_data, 1024 * 1024);
}
close(fd);
free(test_data);

printf(" ✓ 创建了1MB测试文件: %s\n", filename);

// 重新打开文件进行读取
fd = open(filename, O_RDONLY);
if (fd == -1) {
perror(" 打开测试文件失败");
io_destroy(ctx);
unlink(filename);
return -1;
}

// 初始化操作上下文
printf("\n3. 初始化操作上下文:\n");
for (int i = 0; i < 5; i++) {
operation_context_t *op_ctx = &operations&#91;i];
memset(op_ctx, 0, sizeof(*op_ctx));

// 设置不同的取消策略
switch (i % 4) {
case 0:
op_ctx->strategy = CANCEL_STRATEGY_IMMEDIATE;
printf(" 操作 %d: 立即取消策略\n", i + 1);
break;
case 1:
op_ctx->strategy = CANCEL_STRATEGY_TIMEOUT;
op_ctx->timeout_seconds = 2; // 2秒超时
printf(" 操作 %d: 超时取消策略 (2秒)\n", i + 1);
break;
case 2:
op_ctx->strategy = CANCEL_STRATEGY_CONDITIONAL;
op_ctx->condition_value = i * 50; // 不同的条件值
printf(" 操作 %d: 条件取消策略 (条件值: %d)\n", i + 1, op_ctx->condition_value);
break;
case 3:
op_ctx->strategy = CANCEL_STRATEGY_NEVER;
printf(" 操作 %d: 从不取消策略\n", i + 1);
break;
}
}

// 准备异步读取操作
printf("\n4. 准备异步读取操作:\n");
struct iocb *iocb_ptrs&#91;5];

for (int i = 0; i < 5; i++) {
operation_context_t *op_ctx = &operations&#91;i];

// 初始化iocb
memset(&op_ctx->iocb, 0, sizeof(op_ctx->iocb));
op_ctx->iocb.aio_data = i + 1;
op_ctx->iocb.aio_lio_opcode = IOCB_CMD_PREAD;
op_ctx->iocb.aio_fildes = fd;

// 分配读取缓冲区
char *read_buffer = malloc(200 * 1024); // 200KB缓冲区
if (read_buffer) {
op_ctx->iocb.aio_buf = (uint64_t)(uintptr_t)read_buffer;
op_ctx->iocb.aio_nbytes = 200 * 1024;
op_ctx->iocb.aio_offset = i * 200 * 1024; // 不同的偏移量

iocb_ptrs&#91;i] = &op_ctx->iocb;
op_ctx->is_submitted = 1;
op_ctx->submit_time = time(NULL);

printf(" 准备操作 %d: 读取200KB数据\n", i + 1);
}
}

// 提交异步操作
printf("\n5. 提交异步操作:\n");
ret = io_submit(ctx, 5, iocb_ptrs);
if (ret < 0) {
printf(" 提交异步操作失败: %s\n", strerror(-ret));
goto cleanup;
}
printf(" ✓ 成功提交 %d 个异步操作\n", ret);

// 执行取消策略
printf("\n6. 执行取消策略:\n");
time_t start_time = time(NULL);
int completed_operations = 0;
int cancelled_operations = 0;

// 监控和取消操作
while (difftime(time(NULL), start_time) < 10) { // 最多等待10秒
// 检查取消条件
for (int i = 0; i < 5; i++) {
operation_context_t *op_ctx = &operations&#91;i];

if (op_ctx->is_submitted && !op_ctx->is_completed && !op_ctx->is_cancelled) {
if (check_cancel_condition(op_ctx)) {
printf(" 尝试取消操作 %d\n", i + 1);

struct io_event cancel_result;
ret = io_cancel(ctx, &op_ctx->iocb, &cancel_result);
if (ret == 0) {
printf(" ✓ 操作 %d 取消成功\n", i + 1);
op_ctx->is_cancelled = 1;
cancelled_operations++;
} else if (ret == -EAGAIN) {
printf(" ℹ 操作 %d 无法取消\n", i + 1);
} else {
printf(" ✗ 操作 %d 取消失败: %s\n", i + 1, strerror(-ret));
}
}
}
}

// 检查完成事件
struct io_event events&#91;5];
struct timespec timeout = {0, 100000000}; // 100ms超时

ret = io_getevents(ctx, 0, 5, events, &timeout);
if (ret > 0) {
printf(" 收到 %d 个完成事件\n", ret);

for (int i = 0; i < ret; i++) {
int op_index = events&#91;i].data - 1;
if (op_index >= 0 && op_index < 5) {
operation_context_t *op_ctx = &operations&#91;op_index];
op_ctx->is_completed = 1;
completed_operations++;

printf(" 操作 %d 完成: %ld 字节\n",
op_index + 1, events&#91;i].res);
}
}
}

// 检查是否所有操作都已完成或取消
int all_done = 1;
for (int i = 0; i < 5; i++) {
operation_context_t *op_ctx = &operations&#91;i];
if (op_ctx->is_submitted && !op_ctx->is_completed && !op_ctx->is_cancelled) {
all_done = 0;
break;
}
}

if (all_done) {
printf(" 所有操作已完成或取消\n");
break;
}

// 更新条件值(模拟条件变化)
for (int i = 0; i < 5; i++) {
operations&#91;i].condition_value += 10;
}

usleep(100000); // 100ms延迟
}

// 最终统计
printf("\n7. 最终统计:\n");
printf(" 总操作数: 5\n");
printf(" 完成操作数: %d\n", completed_operations);
printf(" 取消操作数: %d\n", cancelled_operations);
printf(" 进行中操作数: %d\n", 5 - completed_operations - cancelled_operations);

// 显示每个操作的最终状态
printf("\n8. 操作状态详情:\n");
for (int i = 0; i < 5; i++) {
operation_context_t *op_ctx = &operations&#91;i];
printf(" 操作 %d: ", i + 1);

if (op_ctx->is_cancelled) {
printf("已取消 ");
} else if (op_ctx->is_completed) {
printf("已完成 ");
} else {
printf("进行中 ");
}

switch (op_ctx->strategy) {
case CANCEL_STRATEGY_IMMEDIATE:
printf("(立即取消策略)");
break;
case CANCEL_STRATEGY_TIMEOUT:
printf("(超时取消策略)");
break;
case CANCEL_STRATEGY_CONDITIONAL:
printf("(条件取消策略)");
break;
case CANCEL_STRATEGY_NEVER:
printf("(从不取消策略)");
break;
}
printf("\n");
}

// 清理资源
cleanup:
printf("\n9. 清理资源:\n");

// 释放缓冲区
for (int i = 0; i < 5; i++) {
if (operations&#91;i].iocb.aio_buf) {
free((void*)(uintptr_t)operations&#91;i].iocb.aio_buf);
}
}

close(fd);
unlink(filename);
io_destroy(ctx);
printf(" ✓ 资源清理完成\n");

return 0;
}

int main() {
return demo_conditional_cancel_strategy();
}

示例5:错误处理和恢复

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>

/**
* 系统调用包装函数
*/
static inline int io_setup(unsigned nr_events, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr_events, ctxp);
}

static inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}

static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}

static inline int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result) {
return syscall(__NR_io_cancel, ctx, iocb, result);
}

static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);
}

/**
* 错误处理上下文
*/
typedef struct {
int error_code;
const char *error_message;
int retry_count;
int max_retries;
time_t error_time;
const char *operation_name;
} error_context_t;

/**
* 记录错误信息
*/
void record_error(error_context_t *ctx, int error_code, const char *operation, const char *message) {
ctx->error_code = error_code;
ctx->error_message = message;
ctx->error_time = time(NULL);
ctx->operation_name = operation;
ctx->retry_count++;

printf("错误记录: %s\n", operation);
printf(" 错误码: %d\n", error_code);
printf(" 错误信息: %s\n", message);
printf(" 重试次数: %d/%d\n", ctx->retry_count, ctx->max_retries);
}

/**
* 错误恢复策略
*/
int apply_recovery_strategy(error_context_t *ctx, aio_context_t aio_ctx, struct iocb *iocb) {
printf("应用错误恢复策略:\n");

switch (ctx->error_code) {
case -EAGAIN:
printf(" EAGAIN错误,操作稍后重试\n");
if (ctx->retry_count < ctx->max_retries) {
printf(" 重试操作...\n");
struct iocb *iocbs&#91;1] = {iocb};
int ret = io_submit(aio_ctx, 1, iocbs);
if (ret == 1) {
printf(" ✓ 重试成功\n");
return 0;
} else {
printf(" ✗ 重试失败: %s\n", strerror(-ret));
record_error(ctx, ret, ctx->operation_name, "重试失败");
}
}
break;

case -ECANCELED:
printf(" ECANCELED错误,操作已被取消\n");
printf(" 尝试重新提交操作...\n");
struct iocb *iocbs&#91;1] = {iocb};
int ret = io_submit(aio_ctx, 1, iocbs);
if (ret == 1) {
printf(" ✓ 重新提交成功\n");
return 0;
} else {
printf(" ✗ 重新提交失败: %s\n", strerror(-ret));
record_error(ctx, ret, ctx->operation_name, "重新提交失败");
}
break;

case -EBADF:
printf(" EBADF错误,文件描述符无效\n");
printf(" 建议:检查文件描述符有效性\n");
break;

case -EINVAL:
printf(" EINVAL错误,参数无效\n");
printf(" 建议:检查参数设置\n");
break;

default:
printf(" 未知错误: %s\n", strerror(-ctx->error_code));
printf(" 建议:记录错误并采取适当措施\n");
break;
}

return -1;
}

/**
* 演示错误处理和恢复
*/
int demo_error_handling_recovery() {
aio_context_t ctx;
struct iocb iocb;
struct io_event result;
int fd;
int ret;
error_context_t error_ctx = {0};

printf("=== 错误处理和恢复演示 ===\n");

// 设置错误处理上下文
error_ctx.max_retries = 3;
error_ctx.retry_count = 0;

// 初始化AIO上下文
printf("1. 初始化AIO上下文:\n");
ctx = 0;
ret = io_setup(32, &ctx);
if (ret < 0) {
record_error(&error_ctx, ret, "io_setup", "初始化AIO上下文失败");
apply_recovery_strategy(&error_ctx, ctx, NULL);
return -1;
}
printf(" ✓ AIO上下文初始化成功\n");

// 创建测试文件
printf("\n2. 创建测试文件:\n");
const char *filename = "error_recovery_test.txt";
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
record_error(&error_ctx, -errno, "open", "创建测试文件失败");
io_destroy(ctx);
return -1;
}
printf(" ✓ 测试文件创建成功\n");

// 准备异步写入操作
printf("\n3. 准备异步写入操作:\n");
const char *test_data = "Error handling and recovery test data.\n";
size_t data_size = strlen(test_data);

memset(&iocb, 0, sizeof(iocb));
iocb.aio_data = 1001;
iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
iocb.aio_fildes = fd;
iocb.aio_buf = (uint64_t)(uintptr_t)test_data;
iocb.aio_nbytes = data_size;
iocb.aio_offset = 0;

printf(" 准备写入操作:\n");
printf(" 数据大小: %zu 字节\n", data_size);
printf(" 用户数据: %llu\n", (unsigned long long)iocb.aio_data);

// 提交异步操作
printf("\n4. 提交异步操作:\n");
struct iocb *iocbs&#91;1] = {&iocb};
ret = io_submit(ctx, 1, iocbs);
if (ret != 1) {
record_error(&error_ctx, ret, "io_submit", "提交异步操作失败");
if (apply_recovery_strategy(&error_ctx, ctx, &iocb) != 0) {
close(fd);
unlink(filename);
io_destroy(ctx);
return -1;
}
}
printf(" ✓ 异步操作提交成功\n");

// 演示各种错误场景
printf("\n5. 演示错误场景:\n");

// 场景1: 尝试取消已完成的操作
printf(" 场景1: 尝试取消已完成的操作\n");
struct io_event events&#91;1];
struct timespec timeout = {2, 0}; // 2秒超时

ret = io_getevents(ctx, 1, 1, events, &timeout);
if (ret > 0) {
printf(" 操作已完成,尝试取消...\n");
ret = io_cancel(ctx, &iocb, &result);
if (ret == -EAGAIN) {
printf(" ✓ 取消失败:操作已完成 (EAGAIN)\n");
} else if (ret == 0) {
printf(" ✓ 操作取消成功\n");
} else {
printf(" 取消操作返回: %s\n", strerror(-ret));
}
}

// 场景2: 使用无效的iocb尝试取消
printf("\n 场景2: 使用无效的iocb尝试取消\n");
struct iocb invalid_iocb;
memset(&invalid_iocb, 0, sizeof(invalid_iocb));
invalid_iocb.aio_data = 9999;

ret = io_cancel(ctx, &invalid_iocb, &result);
if (ret == -EAGAIN) {
printf(" ✓ 取消失败:无效操作 (EAGAIN)\n");
} else {
printf(" 取消操作返回: %s\n", strerror(-ret));
}

// 场景3: 使用无效的上下文ID
printf("\n 场景3: 使用无效的上下文ID\n");
struct iocb test_iocb;
memset(&test_iocb, 0, sizeof(test_iocb));

aio_context_t invalid_ctx = (aio_context_t)-1;
ret = io_cancel(invalid_ctx, &test_iocb, &result);
if (ret == -EINVAL) {
printf(" ✓ 操作失败:无效上下文ID (EINVAL)\n");
} else {
printf(" 取消操作返回: %s\n", strerror(-ret));
}

// 场景4: 重复取消同一个操作
printf("\n 场景4: 重复取消操作\n");
ret = io_cancel(ctx, &iocb, &result);
if (ret == -EAGAIN) {
printf(" ✓ 第二次取消失败:操作已处理 (EAGAIN)\n");
} else if (ret == 0) {
printf(" ✓ 第二次取消成功\n");
ret = io_cancel(ctx, &iocb, &result);
if (ret == -EAGAIN) {
printf(" ✓ 第三次取消失败:操作已处理 (EAGAIN)\n");
}
} else {
printf(" 第二次取消操作返回: %s\n", strerror(-ret));
}

// 演示资源清理错误处理
printf("\n6. 演示资源清理错误处理:\n");

// 正常关闭文件
printf(" 正常关闭文件:\n");
if (close(fd) == 0) {
printf(" ✓ 文件关闭成功\n");
} else {
record_error(&error_ctx, -errno, "close", "关闭文件失败");
printf(" 尝试强制清理...\n");
}

// 删除测试文件
printf(" 删除测试文件:\n");
if (unlink(filename) == 0) {
printf(" ✓ 测试文件删除成功\n");
} else {
record_error(&error_ctx, -errno, "unlink", "删除测试文件失败");
printf(" 注意:可能需要手动清理测试文件\n");
}

// 销毁AIO上下文
printf(" 销毁AIO上下文:\n");
ret = io_destroy(ctx);
if (ret == 0) {
printf(" ✓ AIO上下文销毁成功\n");
} else {
record_error(&error_ctx, ret, "io_destroy", "销毁AIO上下文失败");
printf(" 销毁操作返回: %s\n", strerror(-ret));
}

// 显示错误处理总结
printf("\n=== 错误处理总结 ===\n");
printf("1. 常见错误类型:\n");
printf(" ✓ EAGAIN: 操作无法取消(已完成或不存在)\n");
printf(" ✓ EINVAL: 参数无效\n");
printf(" ✓ EBADF: 文件描述符无效\n");
printf(" ✓ ECANCELED: 操作已被取消\n");

printf("\n2. 错误处理策略:\n");
printf(" ✓ 记录错误信息\n");
printf(" ✓ 根据错误类型采取不同措施\n");
printf(" ✓ 必要时重试操作\n");
printf(" ✓ 优雅降级处理\n");

printf("\n3. 恢复策略:\n");
printf(" ✓ 重试机制\n");
printf(" ✓ 备用方案\n");
printf(" ✓ 资源清理\n");
printf(" ✓ 状态恢复\n");

printf("\n4. 最佳实践:\n");
printf(" ✓ 完善的错误记录\n");
printf(" ✓ 适当的重试策略\n");
printf(" ✓ 资源泄漏预防\n");
printf(" ✓ 用户友好提示\n");

return 0;
}

int main() {
return demo_error_handling_recovery();
}

io_cancel 使用注意事项

系统要求:

内核版本: 需要支持AIO的Linux内核

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

权限要求: 通常不需要特殊权限

架构支持: 支持所有主流架构

取消限制:

操作状态: 只能取消排队或正在执行的操作

时间窗口: 已完成的操作无法取消

资源释放: 取消后需要清理相关资源

错误处理:

EAGAIN: 操作无法取消(已完成或不存在)

EINVAL: 参数无效

EBADF: 文件描述符无效

ECANCELED: 操作已被取消

性能考虑:

取消开销: 取消操作本身也有性能开销

批量处理: 批量取消可能更高效

超时设置: 合理设置超时时间

状态检查: 取消前检查操作状态

安全考虑:

参数验证: 验证所有输入参数

内存管理: 确保缓冲区内存有效

资源清理: 及时清理已取消操作的资源

状态同步: 确保多线程环境下的状态一致性

最佳实践:

及时取消: 不需要的操作及时取消

状态跟踪: 跟踪每个操作的状态

错误处理: 妥善处理取消失败的情况

资源管理: 确保资源得到正确释放

超时机制: 实现合理的超时取消机制

io_cancel vs 相似函数对比

io_cancel vs io_destroy:

1
2
3
4
5
6
// io_cancel: 取消单个操作
io_cancel(ctx, &iocb, &result);

// io_destroy: 销毁整个AIO上下文(取消所有操作)
io_destroy(ctx);

io_cancel vs io_getevents:

1
2
3
4
5
6
// io_cancel: 主动取消操作
io_cancel(ctx, &iocb, &result);

// io_getevents: 被动等待操作完成
io_getevents(ctx, 1, 1, events, &timeout);

常见使用场景

1. 超时处理:

1
2
3
4
5
// 异步操作超时后取消
if (operation_timeout) {
io_cancel(ctx, &iocb, &result);
}

2. 用户中断:

1
2
3
4
5
// 用户取消操作时取消所有相关异步操作
for (int i = 0; i < operation_count; i++) {
io_cancel(ctx, &iocbs&#91;i], &results&#91;i]);
}

3. 资源清理:

1
2
3
// 应用程序退出前取消未完成的操作
io_cancel(ctx, &iocb, &result);

总结

io_cancel 是Linux AIO框架中重要的操作取消函数,提供了:

操作控制: 精确控制异步操作的生命周期

资源管理: 及时释放不需要的资源

错误处理: 完善的错误处理机制

灵活性: 支持多种取消策略

通过合理使用 io_cancel,可以构建更加健壮和灵活的异步I/O应用。在实际应用中,需要注意错误处理、资源管理和性能优化等关键问题。

data-ad-format="auto" data-full-width-responsive="true">