我正在设置一个异步编写器,并希望以此来保证文件上的操作顺序。我在另一个读取pcap文件的程序中将其用作编写器。考虑到我已经尝试在代码中分别使用linux-aio和POSIX aio来在磁盘上写入pcap文件。我需要知道POSIX AIO的aio_write()和lio_listio()是否保证按顺序执行?
在linux-aio中,我使用iocb结构表示写入操作的单个请求。完成固定次数的单个操作后,io_getevents会阻塞,直到完成固定次数报告为止。
struct iocb io_cb;
memset(&io_cb, 0, sizeof(io_cb));
io_cb.aio_fildes = file_descriptor;
io_cb.aio_lio_opcode = IOCB_CMD_PWRITE;
io_cb.aio_reqprio = 0;
io_cb.aio_buf = (__u64)(buffer);
io_cb.aio_nbytes = size;
io_cb.aio_offset = 0;
struct iocb* io_cb_pointer = &io_cb;
static int32_t BLOCKS_COUNT = 1;
syscall(SYS_io_submit, io_context, BLOCKS_COUNT, &io_cb_pointer)
write_count++;
if ((write_count == MAX_EVENT_COUNT) || flush == true)//flush is to flush before exit program.
{
struct io_event* events = (struct io_event *)malloc((write_count) * sizeof(struct io_event));
syscall(SYS_io_getevents, io_context, write_count / 2, MAX_EVENT_COUNT, events, NULL)
}
上面编写负责任的代码会导致Wireshark可以打开正确的pcap输出。
但是我的问题是POSIX aio,它似乎不能保证执行顺序。这段代码如下所示:
aiocb_array = calloc(MAX_EVENT_COUNT, sizeof (struct aiocb*));
aiocb_element = calloc(MAX_EVENT_COUNT, sizeof (struct aiocb));
...
struct aiocb** aiocb_array;
struct aiocb* aiocb_element;
...
static size_t pre_nbytes = 0;
static __off_t pre_offset = 24;//Due to pcap header file length
aiocb_element[write_count].aio_fildes = file_descriptor;
aiocb_element[write_count].aio_lio_opcode = LIO_WRITE;
aiocb_element[write_count].aio_reqprio = 0;
aiocb_element[write_count].aio_buf = (void *)(buffer);
aiocb_element[write_count].aio_nbytes = size;
aiocb_element[write_count].aio_offset = pre_nbytes + pre_offset;
pre_nbytes = size;
pre_offset = aiocb_element[write_count].aio_offset;
aiocb_array[write_count] = &aiocb_element[write_count];
write_count++;
if ((write_count == MAX_EVENT_COUNT) || flush == true )//flush is to flush before exit program.
{
if(flush)
{
if(lio_listio(LIO_WAIT, aiocb_array, write_count, NULL) != 0)
{
printf("Flush lio_listio errno :%d\n", errno);
input->error_code = errno;
return false;
}
}
else
{
if(lio_listio(LIO_NOWAIT, aiocb_array, write_count, NULL) != 0)
{
printf("lio_listio errno :%d\n", errno);
input->error_code = errno;
return false;
}
}
if(write_count == MAX_EVENT_COUNT)
write_count = 0;
}
如上面的代码所示,我准备了aiocb结构的写请求并为其分配了偏移量,因为用于写的文件是在没有附加模式的情况下打开的。该代码段生成的pcap文件具有与输入pcap相同的字节,但是不幸的是,Wireshark无法打开它并显示错误,表明:“捕获文件似乎已损坏或损坏。(pcap:文件具有...... 。字节数据包,大于最大0f 65535)”。但是,当我以LIO_WAIT模式调用lio_listio并将MAX_EVENT_COUNT设置为1时,它将生成正确的pcap输出,可以由Wireshark正确打开。
此外,当我用POSIX的aio_write函数替换lio_listio时,它再次产生损坏的文件。 根据提到的导致正确输出pcap的条件,看来POSIX执行顺序的lio_listio和aio_write函数与程序提交顺序不同!!! 是否以任意顺序执行操作?如果答案是肯定的,为什么它会忽略偏移值并且无法生成正确的输出?为什么linux-aio保证并保持操作顺序? 如果答案是否定的,那么我的代码和逻辑问题是什么?
任何帮助将不胜感激。