我似乎明白了:
POSIX AIOAPI是原型<aio.h>并且您将程序与librt(-lrt)链接,而libaioAPI <libaio.h>和您的程序中的API 与libaio(-laio)链接.
我无法弄清楚:
1.内核是否以不同的方式处理这两种方法中的任何一种?
2. O_DIRECT使用其中任何一个标志是强制性的吗?
正如在这篇文章中提到的,libaio 在没有O_DIRECT使用的情况下工作正常libaio.但是,理解但是:
根据R.Love的Linux系统编程书,Linux只支持常规文件上的aio(我假设它是POSIX AIO).只有在打开O_DIRECT的小程序(使用aio.h,与-lrt链接)调用aio_write时没有O_DIRECT标志打开的文件没有问题.
事件驱动和异步通常用作同义词.这两者有什么不同吗?
另外,epoll和之间有什么区别aio?它们如何结合在一起?
最后,我多次读过Linux中的AIO被严重破坏.究竟是怎么破碎的?
谢谢.
我正在寻找在linux上进行异步文件I/O的最有效方法.
POSIX glibc实现使用userland中的线程.
本机aio内核api仅适用于无缓冲操作,内核补丁用于添加对缓冲操作的支持,但这些补丁已超过3年,似乎没有人关心将它们集成到主线中.
我发现了许多允许异步I/O的其他想法,概念和补丁,尽管其中大多数都是在3年以上的文章中.在今天的内核中真正可用的是什么呢?我已经阅读过有关servlet,acalls,内核线程的内容以及我现在甚至都不记得的更多内容.
在今天的内核中进行缓冲异步文件输入/输出的最有效方法是什么?
考虑一个受CPU限制的应用程序,但也具有高性能I/O要求.
我正在将Linux文件I/O与Windows进行比较,我看不出epoll将如何帮助Linux程序.内核会告诉我文件描述符"准备好读取",但是我仍然需要调用阻塞read()来获取我的数据,如果我想读取兆字节,那么很明显它会阻塞.
在Windows上,我可以创建一个设置了OVERLAPPED的文件句柄,然后使用非阻塞I/O,并在I/O完成时收到通知,并使用该完成函数中的数据.我需要不花费应用程序级别的挂钟时间等待数据,这意味着我可以精确地将我的线程数调整为我的内核数量,并获得100%的高效CPU利用率.
如果我必须在Linux上模拟异步I/O,那么我必须分配一些线程来执行此操作,并且这些线程将花费一些时间来处理CPU事务,并且大量时间阻塞I/O,此外,在这些线程的消息传递中会有开销.因此,我将过度订阅或利用我的CPU核心.
我把mmap()+ madvise()(WILLNEED)视为"穷人的异步I/O",但它仍然没有完全通过那里,因为当它完成时我无法得到通知 - 我有"猜测",如果我猜"错误",我将最终阻止内存访问,等待数据来自磁盘.
Linux似乎在io_submit中启动了异步I/O,它似乎也有一个用户空间POSIX aio实现,但它已经有一段时间了,我知道没有人会担保这些系统的关键,高性能的应用程序.
Windows模型的工作方式大致如下:
步骤1/2通常作为单个事物完成.步骤3/4通常使用工作线程池完成,而不是(必要)与发出I/O相同的线程.这个模型有点类似于boost :: asio提供的模型,除了boost :: asio实际上不会给你异步的基于块的(磁盘)I/O.
Linux中epoll的不同之处在于,在步骤4中,还没有I/O发生 - 它会在步骤4之后提升第1步,如果你确切知道你需要的话,那就是"向后".
编写了大量的嵌入式,桌面和服务器操作系统之后,我可以说这种异步I/O模型对于某些类型的程序来说非常自然.它还具有非常高的吞吐量和低开销.我认为这是Linux I/O模型在API级别上仍然存在的真正缺点之一.
我正在编写一个使用Linux异步I/O系统调用的库,并且想知道为什么该io_submit函数在ext4文件系统上表现出较差的扩展.如果可能,我该怎么做io_submit才能阻止大IO请求大小?我已经做了以下(如描述这里):
O_DIRECT.为了观察内核花了多长时间io_submit,我运行了一个测试,在其中我用dd和创建了1 Gb测试文件/dev/urandom,并重复删除系统缓存(sync; echo 1 > /proc/sys/vm/drop_caches)并读取文件越来越大的部分.在每次迭代中,我打印io_submit了等待读取请求完成所花费的时间和所花费的时间.我在运行Arch Linux的x86-64系统上运行了以下实验,内核版本为3.11.该机器有一个SSD和一个Core i7 CPU.第一个图表绘制了读取的页数与等待io_submit完成所花费的时间.第二个图显示等待读取请求完成所花费的时间.时间以秒为单位.


为了比较,我创建了一个类似的测试,通过使用同步IO pread.结果如下:

似乎异步IO按预期工作,最大请求大小为20,000页.之后,io_submit阻止.这些观察结果导致以下问题:
io_submit不变?用于测试异步IO的代码如下所示.如果您认为它们是相关的,我可以添加其他源列表,但我尝试仅发布我认为可能相关的详细信息.
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <chrono>
#include <iostream>
#include <memory>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
// For `__NR_*` system call definitions.
#include <sys/syscall.h>
#include <linux/aio_abi.h>
static int
io_setup(unsigned n, …Run Code Online (Sandbox Code Playgroud) 我正在测试内核异步io函数(不是posix aio),我正在试图弄清楚它是如何工作的.下面的代码是一个完整的程序,我只需将数组重复写入使用O_DIRECT打开的文件.我在回调函数中遇到错误"写入错过的字节,期望1024得到0"(参见work_done()中的fprintf语句).
对于那些不熟悉内核aio的人,下面的代码执行以下操作:
我在第5步得到一个错误.如果我不使用O_DIRECT打开文件,一切正常,但它胜过了异步写入的目的.有人能告诉我我做错了什么吗?这是内核aio的正确用法,例如,我对回调的使用是否正确?O_DIRECT的使用是否有任何限制?
我用'gcc -Wall test.c -laio'编译
提前致谢.
/*
* File: myaiocp.c
* Author: kmehta
*
* Created on July 11, 2011, 12:50 PM
*
*
* Testing kernel aio.
* Program creates a 2D matrix and writes it multiple times to create a file of desired size.
* Writes are performed using kernel aio functions (io_prep_pwrite, io_submit, etc.)
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <pthread.h>
#include …Run Code Online (Sandbox Code Playgroud) 我在这里问,因为谷歌搜索引导你在档案馆周围愉快的旅行,没有暗示目前的状态.如果你去谷歌,似乎异步IO在2001年到2003年风靡一时,到2006年,有些东西就像epoll并且libaio正在出现; kevent似乎已经消失了,据我所知,仍然没有好的方法来混合基于完成和基于准备的信号,异步sendfile- 甚至可能吗? - 以及单线程事件循环中的所有其他内容.
所以请告诉我,我错了,这一切都很美好! - 而且,重要的是,使用什么API.
在这方面,Linux与FreeBSD和其他操作系统相比如何?
最近我在不同的论坛上看到了这个。据我阅读一些论坛讨论可以看出,它与输入和输出有关。io_uring 究竟是什么?
我正在尝试使用Linux libaio来优化服务器应用程序中的IO性能.我相信我已经完成了所有必要的工作(使用O_DIRECT,将缓冲区与内存页面对齐...).我期待立即调用io_submit返回,但是一个简单的测试显示它实际需要大约80微秒才能在我的核心i7笔记本电脑上返回.我期待太多或我的测试程序有什么问题吗?(用g ++编译--std = c ++ 0x -laio)
#include <unistd.h>
#include <fcntl.h>
#include <libaio.h>
#include <errno.h>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <chrono>
// Open the file for write, return the file descriptor
int open_write(char const* file)
{
int fd = open(file, O_DIRECT|O_CREAT|O_WRONLY, S_IRWXU|S_IRWXG|S_IROTH);
if (fd < 0) {
perror("open_write");
exit(1);
}
}
// Make a buffer of _size_ byte, fill with 'a', return the buffer, it should be aligned to memory page
void* make_write_buffer(size_t size)
{
void* buf …Run Code Online (Sandbox Code Playgroud) io_getevents乍一看,通知机制看起来非常强大,所以我想要一些可以与它一起使用的东西。我只是还没找到任何东西。在 Windows 上,这很简单:只有TransmitFile,它可以异步工作(重叠),并且如果需要的话可以使用某种通知机制(IOCP、事件)。Linux 上一定有类似的东西,对吗?或者,将我的问题放在某种背景下,我将如何在 Linux 上创建一个高效的文件服务器?
我sendfile(2)最近正在阅读,手册页指出:
Run Code Online (Sandbox Code Playgroud)sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.
这让我想到,为什么read()/的组合write()更慢?手册页侧重于必须在用户空间之间进行的额外复制,而不是所需的总调用次数。我简短地查看了用于读写的内核代码,但没有看到副本。
为什么副本首先存在?内核不能在write()不首先将整个内容复制到内核空间的情况下从传递的缓冲区中读取吗?
异步 IO 接口如 AIO 和io_uring? 他们也抄袭吗?
显然,Linux 已经有了 Asyn-IO (AIO) API。我相信它不是完全异步的。那么 AIO 出了什么问题呢?io_uring 如何克服它?
PS:我尝试阅读https://kernel.dk/io_uring.pdf但无法完全理解,因为我与该语言脱节C。
linux ×10
aio ×8
asynchronous ×7
io ×5
linux-kernel ×4
c ×2
c++ ×2
io-uring ×2
epoll ×1
event-driven ×1
ext4 ×1
performance ×1
posix ×1
sendfile ×1
sockets ×1
unix ×1