The efficient execution of socket I / O was allowed using the ports kqueue, epoll, IO IO and the like. Performing asynchronous file I / O is a kind of late visitor (other than overlapping windows and Solaris I / O for early support for posix AIO).
If you are looking for socket I / O, you are probably better off using one of the above mechanisms.
Thus, the main task of AIO is to solve the problem of asynchronous I / O. Most likely, Mac OS X only supports AIO for regular files, not sockets (since kqueue does this much better).
Write operations are usually cached by the kernel and unloaded later. For example, when the read head of a disk passes by the place where the block is to be recorded.
However, for read operations, if you want the kernel to prioritize and order your reads, AIO is really the only option. This is why the kernel can (theoretically) do this better than any user-level application:
- The kernel sees all disk I / O, and not just tasks on the application disk, and can order them globally.
- The kernel (can) know where the head is reading the disk, and can select the reading task that you give it in the optimal order to move the head to the shortest distance.
- The kernel can use its own queue to optimize your read operations.
- You may be able to perform more read operations per system call with lio_listio () than with readv (), especially if your reads are not (logically) contiguous, storing a small portion of the system call overhead.
- Your program might be a little easier with AIO, since you do not need an extra thread to block while reading or writing.
However, posix AIO has a rather inconvenient interface, for example:
- The only effective and well-supported event callbacks are signals that make it difficult to use in the library, because it means using signal numbers from the global process namespace. If your OS does not support real-time signals, this also means that you need to fulfill all your outstanding requests to find out which one is actually completed (for example, for Mac OS X, and not for Linux). Signal capture in a multi-threaded environment also leads to some complex limitations. Usually you cannot respond to an event inside the signal handler, but you need to pick up the signal, put it on the phone, or use signalfd () (on linux).
- lio_suspend () has the same problems as select (), it does not scale very well with the number of jobs.
- lio_listio (), since there is a fairly limited number of tasks that you can go through, and itβs not so easy to find this restriction in a portable way. You must call sysconf (_SC_AIO_LISTIO_MAX), which may fail, in which case you can use the definition AIO_LISTIO_MAX, which is optionally defined, but then you can use 2, which is defined as guaranteed for support.
As for the real application using posix AIO, you can take a look at lighttpd (lighty), which also posted a performance measurement when implementing support.
Most posix platforms now support posix AIO (Linux, BSD, Solaris, AIX, tru64). Windows supports it through overlapping I / O files. I understand that only Solaris, Windows, and Linux really support async. file I / O to the driver itself, while other operating systems emulate asynchronous mode. I / O with kernel threads. Linux is an exception, its posix AIO implementation in glibc emulates asynchronous operations on user-level threads, while its own async I / O interface (io_submit (), etc.) is truly asynchronous up to the driver, assuming the driver supports it .
I find it quite common among OSes not to support posix AIO for any fd, but to limit it to regular files.