其实说白了,也就是想直接尝试利用一下aio +epoll结合代码,在利用人家sendfile的接口,就是替换sendfile,自己随便玩玩传输文件。我采用的是linux原生的libaio,glibc实现的aio貌似很多在吐槽,性能也不好直接别抛弃了。
这里提一下linux libaio的相关结构体,这些可以在/usr/include/libaio.h文件看到,也有io_prep_pread和io_prep_pwrite的实现。
// iocb是提交IO任务时用到的,可以完整地描述一个IO请求
struct iocb {
void *data; //data是留给用来自定义的指针:可以设置为IO完成后的callback函数;
unsigned key; // 这个没有用过
short aio_lio_opcode; // 表示操作的类型:IO_CMD_PWRITE | IO_CMD_PREAD;
short aio_reqprio; // 优先级,不过看内核代码,貌似没有实现,应该属于预留字段
int aio_fildes; // 当然是要操作的fd
union {
struct io_iocb_common c; // 这个字段比较常用,下面会解释
struct io_iocb_vector v;
struct io_iocb_poll poll;
struct io_iocb_sockaddr saddr;
} u;
};
struct io_iocb_common {
void *buf; // 记录IO要操作的buf
unsigned long nbytes; // 记录IO操作字节数
long long offset; // 记录IO操作文件偏移量
unsigned flags; // 为epoll结合设置
unsigned resfd; // 为epoll结合设置
};
// io_event是用来描述返回结果的:
struct io_event {
void *data; // callback回调函数使用
struct iocb *obj; //obj就是之前提交IO任务时的iocb;
unsigned long res; // 处理的字节数
unsigned long res2; // (res2 = 0)是aio处理
};
sendfile的接口 n = sendfile64(fd, ifd, (off64_t*)&offset64, count);就是替换这个玩玩。 count是需要发送的长度,如果count > 100k我就采用aio读取。最多有128个异步IO同时存在,每个IO最多读取4k,最后在将每个IO读取拷贝到一个大buf里面,在用send做发送处理。这个写这个代码,让我知道很多细节处理,部分代码展示。
#define AIO_NUM_EVENTS 128
#define ALIGN_SIZE 512
#define RD_WR_SIZE (4 * 1024)
#define BUF_SIZE_VAYNEDU (512 * 1024)
static int aio_num = 0;
char send_buf_vaynedu[512 * 1024 + 1] = {0};
uint64_t offset_vaynedu;
// 每个io处理回调函数,而且把每个io读到数据拷贝到大buf
void aio_callbac