No Linux, parece que o tempo do sistema de arquivos está sempre alguns milissegundos atrás do tempo do sistema, levando a inconsistências se você quiser verificar se um arquivo foi modificado antes ou depois de um determinado tempo em intervalos de tempo muito estreitos (milissegundos).
Em qualquer sistema Linux com um sistema de arquivos que suporte resolução de nanossegundos (tentei com ext4 com inodes de 256 bytes e ZFS), se você tentar fazer algo como:
date +%H:%M:%S.%N; echo "hello" > test1; stat -c %y test1 | cut -d" " -f 2
o segundo valor de saída (hora de modificação do arquivo) está sempre alguns milissegundos atrás do primeiro (hora do sistema), por exemplo:
17:26:42.400823099
17:26:42.395348462
enquanto deveria ser o contrário, já que o arquivo test1
é modificado após chamar o date
comando.
Você pode obter o mesmo resultado em python:
import os, time
def test():
print(time.time())
with open("test1", "w") as f:
f.write("hello")
print(os.stat("test1").st_mtime)
test()
1698255477.3125281
1698255477.3070245
Por que é tão? E existe uma maneira de evitá-lo, para que a hora do sistema seja consistente com a hora do sistema de arquivos? A única solução alternativa que encontrei até agora é obter o "tempo" do sistema de arquivos (seja lá o que isso signifique na prática) criando um arquivo temporário fictício e obtendo seu horário de modificação, assim:
def get_filesystem_time():
"""
get the current filesystem time by creating a temporary file and getting
its modification time.
"""
with tempfile.NamedTemporaryFile() as f:
return os.stat(f.name).st_mtime
mas me pergunto se existe uma solução mais limpa.
A hora usada para carimbos de data e hora do arquivo é a hora do último tique do temporizador, que está sempre um pouco no passado. A
current_time
função nasinode.c
chamadasktime_get_coarse_real_ts64
:e o último está documentado da seguinte forma :
Observe a menção específica aos carimbos de data/hora do inode.
Não conheço nenhuma maneira de evitar isso completamente, exceto modificar o kernel. Você pode reduzir o impacto aumentando
CONFIG_HZ
. Houve uma proposta recente para melhorar isso , que ainda está sendo trabalhada .A resposta de Stephen Kitt parece acertada.
Podemos reproduzir isso muito bem obtendo o mesmo clock "grosso" que o sistema de arquivos usa, pelo menos na configuração do meu kernel; um programa C que sempre obtém o relógio aproximado em tempo real antes de acessar o arquivo leva exatamente o carimbo de data e hora do arquivo ou (raramente) um carimbo de data e hora um tique do sistema anterior:
produz algo como
com a ocorrência rara mencionada acima de um delta de duração de cerca de tick, que acontece quando o tick do sistema cai apenas entre a obtenção
now_coarse
e a modificação do arquivo:A propósito, as estatísticas mostram que se fizermos o acima até coletarmos 10.000 ocorrências onde esse “salto de tique” aconteceu, o intervalo de possíveis atrasos é bem pequeno:
Em outras palavras, temos um timing extremamente próximo no que diz respeito aos deltas entre os ticks.