Pergunta

O Win32 CreateFile tem FILE_FLAG_DELETE_ON_CLOSE, mas eu 'm no Linux.

Eu quero abrir um arquivo temporário que será sempre excluída após o término do programa. Eu poderia entender que, no caso de uma falha do programa pode não ser prático para garantir isso, mas em qualquer outro caso que eu gostaria que ele funcione.

Eu sei sobre RAII. Eu sei sobre sinais. Eu sei sobre atexit(3). Eu sei que pode abrir o arquivo e excluí-lo imediatamente e o arquivo permanecerá acessível até que o descritor de arquivo está fechado (o que ainda lida com um acidente). Nenhum deles parece ser uma solução completa e simples:

  1. RAII: estado lá, feito isso:. Eu tenho um objeto cujo destruidor apaga o arquivo, mas o destruidor não é chamado se o programa é encerrado por um sinal
  2. sinais: Eu estou escrevendo uma biblioteca de baixo nível que torna registrar um manipulador de sinal uma proposição complicada. Por exemplo, o que acontece se o aplicativo usa sinaliza si? Eu não quero pisar em nenhum dos pés. Eu poderia considerar algum uso inteligente de sigaction(2) para lidar ... mas não colocar o pensamento suficiente para essa possibilidade ainda.
  3. atexit(3):. Aparentemente inútil, uma vez que não é chamado durante terminação anormal (por exemplo, através de um sinal)
  4. unlink(2) preferência: isto é bom muito, exceto que eu preciso do arquivo para permanecer visível no sistema de arquivos (caso contrário, o sistema é mais difícil de monitor / solução de problemas)
  5. .

O que você faria aqui?

Além disso Explicação

Eu elidido um detalhe no meu post original, que agora percebo que eu deveria ter incluído. O "arquivo", neste caso não é estritamente um arquivo normal, mas sim é um POSIX Message Queue. Eu criá-lo via mq_open(). Ele pode ser fechado por meio de mq_close() ou close() (a primeira é uma abreviatura para esta última no meu sistema). Ele pode ser removido a partir do sistema através mq_unlink(). Tudo isso faz com que seja análogo a um arquivo regular, , exceto que não posso escolher o diretório no qual reside o arquivo. Isso faz com que a corrente de resposta mais popular (colocando o arquivo em /tmp) impraticável, porque o "arquivo" é criado pelo sistema em um sistema de arquivos virtual com capacidade muito limitada. (Eu montado o sistema de arquivos virtual no /dev/mqueue, seguindo o exemplo em man mq_overview).

Isso também explica por que eu preciso o nome para permanecer visível (fazendo a abordagem imediato-unlink inviável.): O "arquivo" deve ser compartilhada entre dois ou mais processos

Foi útil?

Solução

A exigência de que o nome permanece visível enquanto o processo estiver em execução torna isso difícil de alcançar. você pode rever essa exigência?

Se não, então provavelmente não é uma solução perfeita. Eu consideraria combinando uma estratégia de manipulação de sinal com o que Kamil Kisiel sugere. Você pode acompanhar os manipuladores de sinais instalados antes de instalar seus manipuladores de sinal. Se o manipulador padrão é SIG_IGN, você normalmente não instalar o seu próprio manipulador; se é SIG_DFL, você lembre-se que; se é algo mais - um manipulador de sinal definido pelo usuário - você lembrar que ponteiro, e instalar o seu próprio. Quando o manipulador foi chamado, você faria tudo o que você precisa fazer, e depois chamar o manipulador lembrado, encadeamento, assim, os manipuladores. Você também iria instalar um manipulador de atexit (). Você faria também o documento que você faça isso, e os sinais de que você fazê-lo.

Note que a manipulação de sinal é uma estratégia imperfeita; SIGKILL não pode ser pego, e o manipulador atexit () não será chamado, eo arquivo será deixado ao redor.

A sugestão de David Segond - um nome de arquivo daemon temporária - é interessante. Para processos simples, é suficiente; se o processo solicitando os garfos de arquivos temporários e espera que a criança possuir o arquivo depois (e saídas), o daemon tem um problema de detectar quando o último processo de usá-lo morrer - porque não sabe automaticamente os processos que têm que abrir.

Outras dicas

Se você está apenas fazendo um arquivo temporário, apenas criá-lo em /tmp ou um subdiretório do mesmo. Em seguida, fazer um melhor esforço para removê-lo quando feito através atexit(3) ou similar. Contanto que você usar nomes únicos escolhidos através mkstemp(3) ou semelhante, mesmo que ele não consegue ser excluído por causa de uma falha de programa, você não correr o risco de lê-lo novamente em execuções subsequentes ou outras condições.

Nesse ponto é apenas um problema ao nível do sistema de manter /tmp limpo. A maioria das distros limpá-lo na inicialização ou desligamento, ou executar um cron regular para apagar arquivos antigos.

Talvez alguém sugeriu isso já, mas eu sou incapaz de detectá-lo, dadas todas as suas necessidades, o melhor que eu posso pensar é ter o nome do arquivo de alguma forma comunicado a um processo pai, como uma start-script, que irá limpeza após as matrizes do processo, tinha ele não conseguiu fazê-lo. Esta é, talvez, mais conhecido como um cão de guarda, mas depois com o caso de uso mais comum adicionado para matar e / ou reiniciar o processo quando ele de alguma forma falhar.

Se o seu dies processo pai, bem, você está praticamente fora de sorte, mas a maioria dos ambientes de script são bastante robustos e raramente morrem menos que o script está quebrado, que muitas vezes é mais fácil manter correto do que um programa.

No passado, eu tenho construir um "gerenciador de arquivos temporários" que manteve o controle de arquivos temporários.

Um teria pedido um nome de arquivo temporário do gerente e este nome foi registrado.

Uma vez que você não precisa do nome de arquivo temporário mais, você informa o gerente e o nome do arquivo não é registrado.

Após a recepção de um sinal de terminação, todos os arquivos temporários registrados foram destruídos.

nomes de arquivos temporários foram UUID base para colisões a evitar.

Você poderia ter o garfo processo depois de criar o arquivo, e depois esperar que a criança perto, e então o pai pode desvincular o arquivo e saia.

Eu só aderiu stackoverflow e encontrei aqui:)

Se você é problema é gerenciar mq arquivos e mantê-los de se acumulando, você não precisa realmente de exclusão do arquivo garantia após a rescisão. Se você só queria arquivos inúteis de se acumulando, do que manter um diário pode ser tudo o que você precisa. Adicionar uma entrada para o arquivo de diário após um mq é aberta, outra entrada quando ele é fechado, e quando sua biblioteca é inicializada, cheque de inconsistência na revista e tomar as medidas necessárias para corrigir a inconsistência. Se você se preocupar em deixar de funcionar quando mq_open/mq_close está sendo chamado, você também pode adicionar uma entrada de jornal pouco antes essas funções forem chamadas.

  • Tenha um diretório de manutenção de livro para arquivos temporários sob o ponto-de diretório.
  • Ao criar um arquivo temp, primeiro criar o arquivo de manutenção de livro para o diretório de contabilidade que contém caminho ou UUID ao seu arquivo a-ser temporário.
  • Criar esse arquivo temporário.
  • Quando temp-arquivo é excluído, exclua o arquivo de manutenção de livro.
  • Quando o programa inicia, verificar o diretório de manutenção de livro para todos os arquivos que contêm caminhos para arquivos temporários e tentar excluí-los, se for encontrado, eles apagar-book manter arquivos.
  • (Log ruidosamente se qualquer etapa falhar.)

Não vejo maneiras de fazer isso de qualquer maneira mais simples. Este é o clichê qualquer programa de qualidade da produção deve passar por; +500 linhas facilmente.

Você realmente precisa do nome para permanecer visível?

Suponha que você tomar a opção de imediatamente desvincular o arquivo. Então:

  • unlink de preferência (2):. Isso é bom bastante, exceto que eu preciso do arquivo para permanecer visível no sistema de arquivos (caso contrário, o sistema é mais difícil de monitor / solução de problemas)

    Você ainda pode depuração em um arquivo excluído, uma vez que ainda será visível sob /proc/$pid/fd/. Contanto que você sabe os pids de seus processos, enumerando os seus arquivos abertos deve ser fácil.

  • os nomes precisam permanecer visível durante a operação normal, porque eles são compartilhados entre programas.

    Você ainda pode compartilhar o arquivo aberto apagado entre os processos, passando ao redor do descritor de arquivo sobre soquetes de domínio Unix. Consulte passar descritor de arquivo entre processos diferentes para mais informações.

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