Fazer E / S de soquete de forma eficiente foi resolvido com kqueue, epoll, portas de conclusão de IO e outros semelhantes. Fazer E / S de arquivo assíncrono é meio tardio (além da E / S sobreposta do Windows e do suporte inicial solaris para posix AIO).
Se você está procurando fazer socket I / O, provavelmente é melhor usar um dos mecanismos acima.
O principal objetivo do AIO é, portanto, resolver o problema de E / S de disco assíncrono. É mais provável que seja por isso que o Mac OS X suporta apenas AIO para arquivos regulares, e não soquetes (já que kqueue faz isso muito melhor de qualquer maneira).
As operações de gravação são normalmente armazenadas em cache pelo kernel e eliminadas posteriormente. Por exemplo, quando o cabeçote de leitura do drive passa pelo local onde o bloco deve ser escrito.
No entanto, para operações de leitura, se você deseja que o kernel priorize e ordene suas leituras, AIO é realmente a única opção. Aqui está porque o kernal pode (teoricamente) fazer isso melhor do que qualquer aplicativo de nível de usuário:
- O kernel vê todas as E / S de disco, não apenas seus trabalhos de disco de aplicativos, e pode ordená-los em um nível global
- O kernel (pode) saber onde está o cabeçote de leitura do disco e pode escolher as tarefas de leitura que você passa para ele na ordem ideal, para mover o cabeçote na menor distância
- O kernel pode tirar vantagem da fila de comandos nativos para otimizar ainda mais suas operações de leitura
- Você pode ser capaz de emitir mais operações de leitura por chamada de sistema usando lio_listio () do que com readv (), especialmente se suas leituras não forem (logicamente) contíguas, economizando um pouquinho de sobrecarga de chamada de sistema.
- Seu programa pode ser um pouco mais simples com AIO, já que você não precisa de um thread extra para bloquear em uma chamada de leitura ou gravação.
Dito isso, posix AIO tem uma interface bastante estranha, por exemplo:
- O único meio eficiente e bem suportado de retorno de chamada de evento é por meio de sinais, o que torna difícil o uso em uma biblioteca, pois significa usar números de sinal do namespace de sinal global de processo. Se o seu sistema operacional não suporta sinais em tempo real, isso também significa que você tem que percorrer todas as suas solicitações pendentes para descobrir qual delas realmente terminou (esse é o caso do Mac OS X, por exemplo, não do Linux). A captura de sinais em um ambiente multithread também cria algumas restrições complicadas. Normalmente, você não pode reagir ao evento dentro do manipulador de sinal, mas tem que gerar um sinal, escrever em um pipe ou usar signalfd () (no linux).
- lio_suspend () tem os mesmos problemas que select (), não se ajusta muito bem ao número de jobs.
- lio_listio (), conforme implementado, tem um número bastante limitado de jobs que você pode passar, e não é trivial encontrar esse limite de forma portável. Você tem que chamar sysconf (_SC_AIO_LISTIO_MAX), que pode falhar, neste caso você pode usar o AIO_LISTIO_MAX define, que não está necessariamente definido, mas então você pode usar 2, que é definido como garantido para ser suportado.
Quanto à aplicação do mundo real usando posix AIO, você poderia dar uma olhada em lighttpd (lighty), que também postou uma medição de desempenho ao introduzir o suporte.
A maioria das plataformas posix suporta posix AIO agora (Linux, BSD, Solaris, AIX, tru64). O Windows oferece suporte por meio de E / S de arquivo sobreposto. Meu entendimento é que apenas Solaris, Windows e Linux realmente suportam assíncrono. arquivo de E / S até o driver, enquanto os outros sistemas operacionais emulam o assíncrono. E / S com threads de kernel. Linux sendo a exceção, sua implementação posix AIO em glibc emula operações assíncronas com threads de nível de usuário, enquanto sua interface de E / S assíncrona nativa (io_submit () etc.) é verdadeiramente assíncrona até o driver, assumindo que o driver suporte isso .
Acredito que seja bastante comum entre os sistemas operacionais não suportar posix AIO para qualquer fd, mas restringi-lo a arquivos regulares.