Pergunta

Eu pensei fsync() faz fflush() internamente, então usando fsync() em um fluxo está ok. Mas estou obtendo um resultado inesperado quando executado em E/S da rede.

Meu snippet de código:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* get fd of the FILE pointer */
fd = fileno(fp);
#ifndef WIN32
ret = fsync(fd);
#else
ret = _commit(fd);
fclose(fp);

Mas parece _commit() não está lavando os dados (tentei no Windows e os dados foram gravados em um sistema de arquivos exportado do Linux).

Quando mudei o código para ser:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);   
...   
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);

Ele libera os dados.

Estou me perguntando se _commit() faz a mesma coisa que fflush(). Alguma entrada?

Foi útil?

Solução

fflush() trabalha em FILE*, apenas libera os buffers internos no FILE* do seu aplicativo para o sistema operacional.

fsync Funciona em um nível mais baixo, ele diz ao sistema operacional para liberar seus buffers na mídia física.

OSS Dados de cache fortemente que você escreve em um arquivo. Se o sistema operacional aplicasse a cada escrita para atingir a unidade, as coisas seriam muito lento. fsync (entre outras coisas) permite controlar quando os dados devem atingir a unidade.

Além disso, o FSYNC/COMMIT funciona em um descritor de arquivo. Não tem conhecimento de um FILE* e não pode liberar seus buffers. FILE* Vive em seu aplicativo, os descritores de arquivos vivem no kernel do sistema operacional, normalmente.

Outras dicas

A função C padrão fflush() e a chamada do sistema POSIX fsync() são conceitualmente um pouco semelhantes. fflush() opera em fluxos de arquivos C (FILE objetos) e, portanto, é portátil.fsync() Operar nos descritores de arquivo POSIX. Ambos fazem com que os dados em buffer sejam enviados para um destino.

Em um sistema POSIX, cada fluxo de arquivos C tem um descritor de arquivo associado, e todas as operações em um fluxo de arquivos C serão implementadas delegando, quando necessário, para as chamadas do sistema POSIX que operam no descritor de arquivo.

Pode -se pensar que um chamado para fflush em um sistema POSIX causaria um write de qualquer dado no buffer do fluxo de arquivos, seguido por uma chamada de fsync() Para o descritor de arquivo desse fluxo de arquivos. Então, em um sistema POSIX, não haveria necessidade de seguir uma chamada para fflush com uma chamada para fsync(fileno(fp)). Mas é esse o caso: há um chamado para fsync a partir de fflush?

Não, chamando fflush em um sistema POSIX não implica que fsync será chamado.

O padrão C para fflush diz (ênfase adicionada)

causa dados não escritos para [o] fluxo a ser entregue no ambiente do host a ser escrito para o arquivo

Dizendo que os dados são ser escrito, em vez disso é é Escrito implica que o buffer adicional pelo ambiente do host é permitido. Esse buffer pelo "ambiente host" pode incluir, para um ambiente POSIX, o buffer interno que fsync libera. Portanto, uma leitura atenta do padrão C sugere que o padrão não requer a implementação do POSIX para ligar fsync.

o Posix Standard Descrição de fflush não declara, como um extensão da semântica C, este fsync é chamado.

Eu poderia dizer isso por simplicidade:

usar fsync() com não streaming arquivos (descritores de arquivos inteiros)

usar fflush() com fluxos de arquivo.

Também aqui está a ajuda do homem:

int fflush(FILE *stream); // flush a stream, FILE* type

int fsync(int fd); // synchronize a file's in-core state with storage device
                    // int type

fflush() e fsync() Pode ser usado para tentar garantir que os dados sejam gravados na mídia de armazenamento (mas nem sempre é possível):

  1. primeiro uso fflush(fp) No fluxo de saída (fp Começar um FILE * obtido de fopen ou um dos fluxos padrão stdout ou stderr) para escrever o conteúdo do buffer associado ao fluxo ao sistema operacional.
  2. Em seguida, use fsync(fileno(fp)) Para dizer ao sistema operacional para escrever seus próprios buffers na mídia de armazenamento.

Observe que isso fileno() e fsync() são funções POSIX que podem não estar disponíveis em todos os sistemas, principalmente os sistemas herdados da Microsoft, onde alternativas podem ser nomeadas _fileno(), _fsync() ou _commit()...

Para forçar o comprometimento de alterações recentes no disco, use as funções Sync () ou fsync ().

fsync () sincronizará todos os dados e metadados do arquivo fornecido com o dispositivo de armazenamento permanente. Ele deve ser chamado logo antes do fechamento do arquivo correspondente.

sincronizar() Cometerá todos os arquivos modificados no disco.

Acho que abaixo o documento do Python (https://docs.python.org/2/library/os.html) esclarece muito bem.

OS.FSYNC (FD) Write de arquivo com o Filedescriptor FD no disco. No Unix, isso chama a função fsync () nativa; No Windows, a função MS _Commit ().

Se você estiver começando com um objeto de arquivo python f, primeiro do f.flush () e depois faça o OS.FSYNC (F.FileNo ()), para garantir que todos os buffers internos associados ao F sejam gravados no disco.

Disponibilidade: Unix e Windows a partir de 2.2.3.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top