E/S síncrona e assíncrona
Consulte também aplicativos de exemplo relacionados a E/S.
Existem dois tipos de sincronização de entrada/saída (E/S): E/S síncrona e E/S assíncrona. E/S assíncrona também é conhecida como E/S sobreposta.
Em arquivo síncrono, um thread inicia uma operação de E/S e entra imediatamente em um estado de espera até que a solicitação de E/S seja concluída. Um thread executando arquivo assíncrono de E/S envia uma solicitação de E/S para o kernel chamando uma função apropriada. Se a solicitação for aceita pelo kernel, o thread de chamada continuará processando outro trabalho até que o kernel sinalize ao thread que a operação de E/S está concluída. Em seguida, ele interrompe seu trabalho atual e processa os dados da operação de E/S conforme necessário.
Os dois tipos de sincronização são ilustrados na figura a seguir.
de E/S síncronas e assíncronas
Em situações em que se espera que uma solicitação de E/S leve uma grande quantidade de tempo, como uma atualização ou backup de um banco de dados grande ou um link de comunicação lento, a E/S assíncrona geralmente é uma boa maneira de otimizar a eficiência do processamento. No entanto, para operações de E/S relativamente rápidas, a sobrecarga de processamento de solicitações de E/S do kernel e sinais do kernel pode tornar a E/S assíncrona menos benéfica, particularmente se muitas operações de E/S rápidas precisarem ser feitas. Nesse caso, a E/S síncrona seria melhor. Os mecanismos e detalhes de implementação de como realizar essas tarefas variam dependendo do tipo de identificador de dispositivo que é usado e as necessidades particulares do aplicativo. Em outras palavras, geralmente há várias maneiras de resolver o problema.
Considerações de E/S síncronas e assíncronas
Se um arquivo ou dispositivo for aberto para E/S síncrona (ou seja, FILE_FLAG_OVERLAPPED não for especificado), chamadas subsequentes para funções como WriteFile poderão bloquear a execução do thread de chamada até que ocorra um dos seguintes eventos:
- A operação de E/S é concluída (neste exemplo, uma gravação de dados).
- Ocorre um erro de E/S. (Por exemplo, o tubo é fechado da outra extremidade.)
- Foi cometido um erro na própria chamada (por exemplo, um ou mais parâmetros não são válidos).
- Outro thread no processo chama a funçãoCancelSynchronousIo dousando a alça de thread do thread bloqueado, que encerra a E/S desse thread, falhando na operação de E/S.
- O thread bloqueado é encerrado pelo sistema; por exemplo, o processo em si é encerrado ou outro thread chama a função TerminateThread usando o identificador do thread bloqueado. (Isso geralmente é considerado um último recurso e não é um bom design de aplicativo.)
Em alguns casos, esse atraso pode ser inaceitável para o design e a finalidade do aplicativo, portanto, os designers de aplicativos devem considerar o uso de E/S assíncronas com objetos de sincronização de thread apropriados, como portas de conclusão de E/S . Para obter mais informações sobre a sincronização de threads, consulte Sobre a sincronização.
Um processo abre um arquivo para E/S assíncrona em sua chamada para CreateFile especificando o sinalizador de FILE_FLAG_OVERLAPPED no parâmetro dwFlagsAndAttributes. Se FILE_FLAG_OVERLAPPED não for especificado, o arquivo será aberto para E/S síncrona. Quando o arquivo tiver sido aberto para E/S assíncrona, um ponteiro para uma estrutura deOVERLAPPED será passado para a chamada para ReadFile e WriteFile. Ao executar E/S síncronas, essa estrutura não é necessária em chamadas para ReadFile e WriteFile.
Observação
Se um arquivo ou dispositivo for aberto para E/S assíncrona, chamadas subsequentes para funções como WriteFile usando esse identificador geralmente retornam imediatamente, mas também podem se comportar de forma síncrona em relação à execução bloqueada. Para obter mais informações, consulte E/S de disco assíncrono aparece como síncrona no Windows.
Embora CreateFile seja a função mais comum a ser usada para abrir arquivos, volumes de disco, pipes anônimos e outros dispositivos semelhantes, as operações de E/S também podem ser executadas usando um identificador typecast de outros objetos do sistema, como um soquete criado pelode soqueteou aceitar funções.
Os identificadores para objetos de diretório são obtidos chamando a função CreateFile com o atributo FILE_FLAG_BACKUP_SEMANTICS. Os identificadores de diretório quase nunca são usados — os aplicativos de backup são um dos poucos aplicativos que normalmente os usam.
Depois de abrir o objeto de arquivo para E/S assíncrona, uma estrutura deOVERLAPPED deve ser criada, inicializada e passada corretamente para cada chamada para funções como ReadFile e WriteFile. Tenha em mente o seguinte ao usar a estrutura deOVERLAPPED em operações assíncronas de leitura e gravação:
- Não desaloque ou modifique a estruturaOVERLAPPED ou o buffer de dados até que todas as operações de E/S assíncronas para o objeto de arquivo tenham sido concluídas.
- Se você declarar seu ponteiro para a estrutura deOVERLAPPED como uma variável local, não saia da função local até que todas as operações de E/S assíncronas para o objeto de arquivo tenham sido concluídas. Se a função local for encerrada prematuramente, a estrutura OVERLAPPED sairá do escopo e ficará inacessível a qualquerReadFileou funções WriteFile que encontrar fora dessa função.
Você também pode criar um evento e colocar o identificador na estruturaOVERLAPPED; as funções de espera podem ser usadas para aguardar a conclusão da operação de E/S aguardando na alça de eventos.
Como dito anteriormente, ao trabalhar com um identificador assíncrono, os aplicativos devem ter cuidado ao fazer determinações sobre quando liberar recursos associados a uma operação de E/S especificada nesse manipulador. Se o identificador for desalocado prematuramente, ReadFile ou WriteFile podem relatar incorretamente que a operação de E/S foi concluída. Além disso, a função WriteFile às vezes retornará TRUE com um valor GetLastError de ERROR_SUCCESS, mesmo que esteja usando um identificador assíncrono (que também pode retornar FALSE com ERROR_IO_PENDING). Programadores acostumados com o design de E/S síncrona geralmente liberam recursos de buffer de dados neste momento porque TRUE e ERROR_SUCCESS significam que a operação está concluída. No entanto, se portas de conclusão de E/S estiverem sendo usadas com esse identificador assíncrono, um pacote de conclusão também será enviado mesmo que a operação de E/S seja concluída imediatamente. Em outras palavras, se o aplicativo liberar recursos após WriteFile retornar TRUE com ERROR_SUCCESS além da rotina de porta de conclusão de E/S, ele terá uma condição de erro livre de duplas. Neste exemplo, a recomendação seria permitir que a rotina portuária de conclusão fosse a única responsável por todas as operações de liberação de tais recursos.
O sistema não mantém o ponteiro de arquivo em identificadores assíncronos para arquivos e dispositivos que suportam ponteiros de arquivo (ou seja, dispositivos de busca), portanto, a posição do arquivo deve ser passada para as funções de leitura e gravação nos membros de dados de deslocamento relacionados da estrutura deOVERLAPPED. Para obter mais informações, consulte WriteFile e ReadFile.
A posição do ponteiro do arquivo para um identificador síncrono é mantida pelo sistema à medida que os dados são lidos ou gravados e também pode ser atualizada usando oSetFilePointerou função de SetFilePointerEx.
Um aplicativo também pode esperar no identificador de arquivo para sincronizar a conclusão de uma operação de E/S, mas isso requer extrema cautela. Cada vez que uma operação de E/S é iniciada, o sistema operacional define o identificador de arquivo para o estado não sinalizado. Cada vez que uma operação de E/S é concluída, o sistema operacional define o identificador de arquivo para o estado sinalizado. Portanto, se um aplicativo inicia duas operações de E/S e aguarda no identificador de arquivo, não há como determinar qual operação será concluída quando o identificador estiver definido para o estado sinalizado. Se um aplicativo precisar executar várias operações de E/S assíncronas em um único arquivo, ele deverá aguardar o identificador de evento na estrutura deespecíficaOVERLAPPED para cada operação de E/S, em vez de no identificador de arquivo comum.
Para cancelar todas as operações de E/S assíncronas pendentes, use:
- CancelIo—esta função cancela apenas as operações emitidas pelo thread de chamada para o identificador de arquivo especificado.
- CancelIoEx—esta função cancela todas as operações emitidas pelos threads para o identificador de arquivo especificado.
Use CancelSynchronousIo para cancelar operações de E/S síncronas pendentes.
O ReadFileEx e funções de WriteFileEx permitem que um aplicativo especifique uma rotina a ser executada (consulte FileIOCompletionRoutine) quando a solicitação de E/S assíncrona for concluída.