网络上有一堆 aio的例子和说明
但是 我找了半天 都没有一个能运行的例子。一段代码不能运行和shi有什么区别?
下面的例子是直接把一个person list写入裸盘,再读出来进行校验的例子。
#include <iostream>
#include <vector>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <libaio.h>
#include <sys/stat.h>
#define BLOCK_SIZE 4096 // 块大小
// g++ ComplicatedAIO.cc -o ComplicatedAIO -laio
struct person {
std::string name;
int age{};
[[nodiscard]] size_t size() const {
return sizeof(int) + name.size() + 1;
}
// 参数是指针的指针 外部实参 的值也被修改了
size_t serialize(char **ptr) const {
size_t serialized_size = 0;
memcpy(*ptr, &age, sizeof(int));
serialized_size += sizeof(int);
*ptr += sizeof(int);
memcpy(*ptr, name.c_str(), name.size() + 1); // 包括终止符
serialized_size += name.size() + 1;
*ptr += name.size() + 1;
return serialized_size; // 返回序列化后的总长度
}
void deserialize(const char *buffer) {
memcpy(&age, buffer, sizeof(int));
name = std::string(buffer + sizeof(int));
}
[[nodiscard]] std::string toString() const {
return name + " " + std::to_string(age);
}
};
io_context_t ctx;
int fd;
std::vector<person> prepare_data() {
std::vector<person> people = {
{"Boxb", 25},
{"dale", 33},
{"Charlie", 15}
};
return people;
}
bool is_block_device(int myfd) {
struct stat st{};
if (fstat(myfd, &st) == -1) {
perror("fstat");
return false;
}
return S_ISBLK(st.st_mode);
}
void init_aio(const std::string &device) {
// 打开设备文件,使用 O_DIRECT 和 O_SYNC 标志以确保直接 I/O
fd = open(device.c_str(), O_RDWR | O_DIRECT | O_SYNC);
if (fd < 0) {
perror("open");
exit(1);
}
// 初始化 AIO 上下文
if (io_setup(1, &ctx) < 0) {
perror("io_setup");
close(fd);
exit(1);
}
if (is_block_device(fd)) {
std::cout << device << " is block_device" << std::endl;
} else {
std::cerr << "The file descriptor does not refer to a block device" << std::endl;
close(fd);
exit(1);
}
}
size_t async_write(const std::vector<person> &people, off_t offset) {
size_t predict_size = 0;
for (const person& p: people) {
predict_size += p.size();
}
size_t aligned_total_size = (predict_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
// 分配并初始化缓冲区,确保对齐到扇区边界
void *buffer;
if (posix_memalign(&buffer, BLOCK_SIZE, aligned_total_size) != 0) {
perror("posix_memalign");
io_destroy(ctx);
close(fd);
exit(1);
}
if (!buffer) {
perror("memalign");
io_destroy(ctx);
close(fd);
exit(1);
}
// 序列化数据到缓冲区
size_t exact_size = 0;
char *ptr = static_cast<char *>(buffer);
for (const auto &p: people) {
exact_size += p.serialize(&ptr);
}
memset(ptr, 0, aligned_total_size - exact_size);
std::cout << "predict_size:" << predict_size <<
" exact_size:" << exact_size <<
" aligned_total_size:" << aligned_total_size << std::endl;
// 准备 I/O 控制块
struct iocb cb{};
// io_prep_pwrite 的第四个参数 必须是 block的整数倍
io_prep_pwrite(&cb, fd, buffer, aligned_total_size, offset);
// 提交 I/O 请求
struct iocb *cbs[1] = {&cb};
if (io_submit(ctx, 1, cbs) != 1) {
perror("io_submit");
free(buffer);
io_destroy(ctx);
close(fd);
exit(1);
}
// 等待 I/O 完成
struct io_event events[1];
if (io_getevents(ctx, 1, 1, events, nullptr) != 1) {
perror("io_getevents");
free(buffer);
io_destroy(ctx);
close(fd);
exit(1);
}
// 检查 I/O 结果
if (events[0].res != aligned_total_size) {
std::cerr << "Write error: " << events[0].res << " bytes written, expected is " << aligned_total_size
<< std::endl;
} else {
std::cout << "Successfully wrote " << events[0].res << " bytes to the device." << std::endl;
}
free(buffer);
return aligned_total_size;
}
std::vector<person> async_read(off_t offset, size_t total_size) {
// 分配并初始化缓冲区,确保对齐到扇区边界
void *buffer;
size_t aligned_total_size = (total_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
posix_memalign(&buffer, BLOCK_SIZE, aligned_total_size);
if (!buffer) {
perror("memalign");
io_destroy(ctx);
close(fd);
exit(1);
}
// 准备 I/O 控制块
struct iocb cb{};
io_prep_pread(&cb, fd, buffer, total_size, offset);
// 提交 I/O 请求
struct iocb *cbs[1] = {&cb};
if (io_submit(ctx, 1, cbs) != 1) {
perror("io_submit");
free(buffer);
io_destroy(ctx);
close(fd);
exit(1);
}
// 等待 I/O 完成
struct io_event events[1];
if (io_getevents(ctx, 1, 1, events, nullptr) != 1) {
perror("io_getevents");
free(buffer);
io_destroy(ctx);
close(fd);
exit(1);
}
// 检查 I/O 结果
if (events[0].res != total_size) {
std::cerr << "Read error: " << events[0].res << " bytes Read, expected is " << total_size << std::endl;
}else {
std::cout << "Successfully read " << events[0].res << " bytes to the device." << std::endl;
}
// 反序列化数据
std::vector<person> people;
char *ptr = static_cast<char *>(buffer);
while (ptr < static_cast<char *>(buffer) + total_size) {
person p;
p.deserialize(ptr);
people.push_back(p);
ptr += sizeof(int) + p.name.size() + 1;
}
free(buffer);
return people;
}
int main() {
// 这个盘 必须是裸盘 如果挂载了文件系统 直接写入会覆盖数据
// std::string device = "/dev/sdb";
// 初始化 AIO
init_aio(device);
// 准备数据
std::vector<person> people = prepare_data();
// 异步写入
off_t write_offset = BLOCK_SIZE * 0; // 从偏移量 0 开始写入
size_t write_size = async_write(people, write_offset);
// 异步读取
std::vector<person> read_people = async_read(write_offset, write_size);
// 验证数据
bool success = true;
bool success = true;
for (size_t i = 0; i < people.size(); ++i) {
if (people[i].name != read_people[i].name || people[i].age != read_people[i].age) {
std::cerr << "Data mismatch at index " << i << ": "
<< "expected (" << people[i].name << ", " << people[i].age << "), "
<< "got (" << read_people[i].name << ", " << read_people[i].age << ")\n";
success = false;
} else {
std::cout << people[i].toString() << std::endl;
}
}
if (success) {
std::cout << "Data verification successful.\n";
} else {
std::cerr << "Data verification failed.\n";
}
// 清理
io_destroy(ctx);
close(fd);
return 0;
}
6742

被折叠的 条评论
为什么被折叠?



