Alguns meses atrás, escrevi um post sobre a introdução do I/O Ring no Windows. Depois de postá-lo, várias pessoas pediram para comparar o anel de E/S do Windows e o io_uring Linux, então decidi fazer exatamente isso:
Resposta curta: a implementação do Windows é quase idêntica à implementação do Linux, especialmente ao usar a função wrapper fornecida pelas bibliotecas auxiliares.
Resposta longa: é isso que abordarei no restante deste post.
Informações sobre a implementação de io_uring foram coletadas principalmente aqui https://kernel.dk/io_uring.pdf - um documento que descreve a implementação interna e o uso de io_uring no Linux e explica alguns dos motivos de sua existência e como foi criada.
Como eu disse, a implementação básica de ambos os mecanismos é muito semelhante - ambos são construídos em torno de uma fila de envio e uma fila de conclusão, que têm representações comuns nos espaços de endereço do usuário e do kernel. O aplicativo grava os dados da operação solicitada na fila de envio e os passa para o kernel, que processa o número solicitado de gravações e grava os resultados na fila de conclusão. Em ambos os casos, há um número máximo de entradas permitidas por toque, e a fila de conclusão pode ter até. No entanto, existem algumas diferenças na estrutura interna, bem como em como o aplicativo deve interagir com o anel de E/S.
Inicialização e mapeamento de memória
Uma dessas diferenças é a etapa de inicialização e mapeamento de filas para o espaço do usuário: no Windows, o kernel inicializa completamente o novo anel, incluindo a criação de ambas as filas e a criação de uma visão compartilhada no espaço de endereço do modo de usuário do aplicativo usando MDL. No entanto, na implementação Linux de io_uring, o sistema cria o anel e as filas solicitados, mas não os mapeia para o espaço do usuário. Espera-se que o aplicativo chame mmap(2) usando os descritores de arquivo apropriados para mapear ambas as filas para seu espaço de endereço, bem como uma matriz SQE separada da fila principal.
Esta é outra diferença digna de nota: no Linux, o anel de conclusão (ou fila) contém diretamente a matriz CQE, enquanto o anel de envio não. Em vez disso, o campo sqes no anel de envio é um ponteiro para outra área de memória contendo uma matriz de SQEs a serem mapeados separadamente. Para indexar esse array, sqring tem um campo de array adicional que contém o índice no array SQE. Não sendo um especialista em Linux, não tentarei explicar o motivo desse design, mas simplesmente apresentarei o raciocínio dado no artigo mencionado acima:
Isso pode parecer estranho e confuso no começo, mas existem algumas razões por trás disso. Alguns aplicativos podem incorporar blocos de consulta em suas estruturas de dados internas, e isso permite que eles façam isso de maneira flexível, ao mesmo tempo em que podem enviar várias consultas em uma única operação. Isso, por sua vez, facilita a conversão desses aplicativos para a interface io_uring.
Existem apenas duas regiões importantes no Windows porque os SQEs fazem parte do anel de envio. Na verdade, ambos os anéis são alocados pelo sistema na mesma área de memória, portanto, há apenas uma visão compartilhada entre o usuário e o espaço do kernel contendo dois anéis separados.
Outra diferença existe na hora de criar um novo anel de E/S: no Linux, o número de entradas no anel de envio pode ser de 1 a 0x1000 (4096), enquanto no Windows pode ser de 1 a 0x10000, mas sempre será no mínimo 8 entradas. se destacarem. Em ambos os casos, a fila de conclusão conterá o dobro de entradas da fila de envio. Há uma pequena diferença em relação ao número exato de registros solicitados para um anel: por motivos técnicos, o número de registros em ambos os anéis deve ser uma potência de dois. No Windows, o sistema pega o tamanho do anel solicitado e o alinha com a potência de dois mais próxima para obter o tamanho real que será usado para alocar a memória do anel. No Linux, o sistema não faz isso e espera-se que o aplicativo solicite um tamanho que seja uma potência de dois.
Versões
O Windows coloca muito mais ênfase na compatibilidade do que o Linux, colocando muito esforço para garantir que, quando um novo recurso for lançado, os aplicativos que o utilizam possam funcionar corretamente em diferentes compilações do Windows, mesmo que o recurso mude. Por esta razão, o Windows implementa versionamento para suas estruturas e funções, enquanto o Linux não. O Windows também implementa anéis de E/S em estágios, marcados por versões em que as primeiras versões implementam apenas leituras, a próxima versão implementa gravações e liberações e assim por diante. Ao criar um anel de E/S, o chamador deve passar uma versão para indicar qual versão do anel de E/S deseja usar.
No entanto, no Linux, esse recurso foi totalmente implementado desde o início e não requer controle de versão. Além disso, o Linux não dá tanta ênfase à compatibilidade, e espera-se que os usuários do io_uring usem e ofereçam suporte aos recursos mais recentes.
Aguardando a conclusão de uma operação
Tanto no Windows quanto no Linux, o chamador não precisa esperar que os eventos no anel de E/S sejam concluídos, mas simplesmente ser notificado de que todas as operações foram concluídas, tornando essa função completamente assíncrona. Em ambos os sistemas, o chamador também pode optar por aguardar todos os eventos de forma totalmente síncrona, especificando um tempo limite caso o processamento do evento demore muito. Tudo no meio é uma área onde os sistemas diferem.
No Linux, o chamador pode pedir para aguardar a conclusão de um determinado número de operações no anel, o que o Windows não permite. Esse recurso permite que os aplicativos comecem a processar os resultados após a conclusão de um determinado número de operações, em vez de esperar por todas elas. Em compilações mais recentes, o Windows adicionou uma opção semelhante, mas um pouco mais limitada, registrando um evento de notificação a ser definido quando a primeira entrada no anel for concluída, para sinalizar a um aplicativo em espera que é seguro começar a processar os resultados agora.
Bibliotecas de suporte
Em ambos os sistemas, um aplicativo pode gerenciar seus próprios anéis usando chamadas de sistema. Essa é uma opção permitida no Linux e fortemente desencorajada no Windows, onde a API do NT não está documentada e não deve ser usada oficialmente em código que não seja da Microsoft. No entanto, em ambos os sistemas, a maioria dos aplicativos não precisa gerenciar os próprios anéis, e muito do código geral de gerenciamento de anéis pode ser abstraído e gerenciado por um componente separado.
Isso é feito usando bibliotecas auxiliares - KernelBase.dll no Windows e liburing no Linux.
Ambas as bibliotecas exportam funções comuns, como criar, inicializar e excluir um anel de E/S, criar entradas de fila de envio, enviar um anel e obter um resultado de uma fila de conclusão.
Ambas as bibliotecas usam funções e estruturas de dados muito semelhantes, o que simplifica muito a tarefa de portar o código de uma plataforma para outra.
Conclusão
A implementação de anéis de E/S do Windows é tão semelhante ao io_uring do Linux que parece que alguns dos cabeçalhos foram quase copiados da implementação do io_uring. Existem algumas diferenças entre os dois recursos, principalmente devido às diferenças filosóficas entre os dois sistemas e aos papéis e responsabilidades que eles atribuem ao usuário. O Linux io_uring foi adicionado há alguns anos, tornando-o um recurso mais maduro do que a nova implementação do Windows, embora ainda relativamente jovem e com problemas. Será interessante ver para onde vão essas duas funções no futuro e que paridade terão daqui a alguns anos.
links
https://windows-internals.com/investiga … ion-ports/
https://windows-internals.com/an-end-to-kaslr-bypasses/
https://windows-internals.com/understan … rotection/
https://windows-internals.com/one-i-o-r … -all-a-fuh
https://windows-internals.com/one-year- … t-changed/
https://windows-internals.com/hyperguar … g-extents/
https://windows-internals.com/an-exerci … -analysis/
https://windows-internals.com/hyperguar … g-extents/
https://windows-internals.com/hyperguar … alization/
https://windows-internals.com/ioring-vs … entations/
De TS
Este artigo é uma tradução, o original está disponível https://windows-internals.com/ioring-vs … entations/