Tradução automática, não revista por um falante nativo. O inglês é a referência.

TemporizaçãoEditar no GitHubFonte: docs/CLOCK-LOG-FORMATS.md

Formatos de registos de relógio

src/clock_log.rs lê um registo de relógio medido para uma única série de fase normalizada: uma grelha uniforme de amostras (time_s, phase_s), com o intervalo de amostragem tau0 indicado ou encontrado, cada lacuna contada e as unidades do registo nomeadas. São lidos oito formatos, cada um um subconjunto documentado. Tudo o que fica fora do subconjunto é recusado com um erro que nomeia o que foi encontrado, em vez de ser lido de forma aproximada.

Abreviaturas. RINEX é o Receiver Independent Exchange Format. TICC é o contador de intervalos de tempo da TAPR (Tucson Amateur Packet Radio). ADEV é o desvio de Allan sobreposto, TDEV o desvio de tempo e MTIE o erro máximo de intervalo de tempo. tau0 é o intervalo de amostragem em segundos.

Onde um registo pode ser usado#

  • telecom-timing: [series.clock_log] em vez de series.samples ou series.csv_path. A fase do registo, em ns, é a série de erro de tempo verificada face às máscaras, e o relatório ganha um bloco clock_log a indicar como foi lido.
  • O tipo de cenário do relógio: uma tabela [clock_log] acrescenta à execução um bloco measured: como o registo foi lido, o SHA-256 da tabela (input_sha256; o scenario_hash da execução não abrange a tabela) e das amostras de fase, e o ADEV sobreposto, o TDEV e o MTIE a fatores de média em oitavas. Requer runs = 1. O holdover simulado não se altera.

Sem a tabela, ambos os tipos de cenário são analisados, calculam o hash e reportam exatamente como antes.

[clock_log]                 # or [series.clock_log] in a telecom-timing scenario
format = "ticc"             # "rinex-clk", "timelab", "ticc", "ptp4l", "phc2sys", "ts2phc",
                            # "chrony-tracking" or "chrony-statistics"
path = "logs/ticc.txt"      # or text = "..." inline (the only choice in WebAssembly)
channel = "chA"             # TICC: needed when the log holds more than one channel
gaps = "linear"             # "refuse" (default), "longest" or "linear"
# clock = "G08"             # RINEX, linuxptp, chrony: needed when the log holds more than one clock or source
# tau0_s = 1.0              # overrides a header and the detected spacing
# units = "ns"              # TimeLab phase units: s (default), ms, us, ns, ps
# data = "phase"            # TimeLab: phase (default) or frequency

Os formatos#

rinex-clk: ficheiros de relógio RINEX, versões 2,00 e 3,00 a 3,04 (incluindo o campo de nome de nove caracteres da 3,04). O registo RINEX VERSION / TYPE é verificado e qualquer outra versão é recusada, nomeando a versão encontrada: o IGS publica o formato de relógio (rinex_clock300.txt, 302, 304) até à 3,04, e os documentos RINEX 4,00, 4,01 e 4,02 definem apenas ficheiros de observação, de navegação e meteorológicos, portanto não existe versão 4,00 do ficheiro de relógio a ler. O cabeçalho é lido apenas para o seu TIME SYSTEM ID e é ignorado até END OF HEADER. Dos registos de dados, apenas os registos AS (satélite) e AR (recetor ou estação) de um relógio, selecionado pelo nome, são mantidos. O seu primeiro campo de valor, o viés do relógio em segundos, é a fase. As linhas de continuação e os registos CR, DR e MS são ignorados. As épocas são os campos de calendário do registo, em segundos a partir de 1980-01-06 00:00:00 no sistema de tempo do próprio ficheiro, sem conversão.

timelab: registos ASCII de fase ou frequência no estilo TimeLab, a forma em texto simples que o TimeLab exporta e que a sua importação ASCII e o Stable32 leem. Há uma leitura por linha: ou uma única coluna a um tau0 uniforme, ou duas colunas time value. As colunas podem ser separadas por espaços em branco, vírgulas ou pontos e vírgulas.

  • As linhas que começam por #, ; ou % são comentários. Um comentário da forma key = value (ou key: value) define tau0 (s), units (s, ms, us, ns ou ps, para fase), data (phase ou frequency) ou time_units (s ou mjd, para a primeira de duas colunas).
  • Uma linha inicial não numérica é tomada como cabeçalho de colunas.
  • Os dados de frequência (frequência fracionária) só são aceites como coluna única. São integrados em fase como x[i+1] = x[i] + y[i]·tau0 (NIST SP 1065, 2008, §4,1).
  • Os ficheiros binários e de projeto .tim do TimeLab não são lidos.

ticc: registos do contador TICC da TAPR (Manual de Operação do TICC, revisões de 23 de novembro de 2016 e 15 de dezembro de 2025, "modos de medição"). Todo campo de dados é em segundos com 12 casas decimais (11 por predefinição a partir do firmware 20251101: qualquer quantidade até 15 é lida). Um carimbo de tempo é lido a partir do seu texto decimal como um número inteiro de femtossegundos, e não como um número binário de ponto flutuante, de modo que a fase de um registo obtido dias após o início do contador mantém a resolução própria do contador: um carimbo de tempo f64 em 3.0e5 s tem um espaçamento de 5.8e-11 s, cerca dos 60 ps do contador.

  • As linhas do modo de marca temporal (<seconds> chA, <seconds> chB) e o canal de pseudomarca temporal do modo TimeLab (chC) são marcas temporais de eventos. A fase do canal selecionado é a sua marca temporal menos o tique nominal: x[k] = t[k] − t[0] − n[k]·tau0, em que n[k] é o número inteiro de tau0 desde o primeiro evento. Um evento perdido é uma lacuna.
  • As linhas do modo de intervalo (<seconds> TI(A->B), ou qualquer etiqueta que comece por TI) são lidas diretamente como fase, uma leitura por tau0. O cenário tem de indicar tau0_s, porque a linha não transporta tempo.
  • O modo Paired Timestamp imprime as mesmas linhas na ordem dos canais e é lido como modo Timestamp; o modo 3-Corner Hat acrescenta o chC sintetizado, lido como acima.
  • A saída dos modos Period e Debug é recusada. Um canal cujas leituras não crescem é comunicado como modo Period. O modo Binary Timestamp não é texto, e um ficheiro nesse modo é recusado com uma mensagem que o diz.
  • As linhas que começam por #, e as linhas que não são <number> <label> (como o menu de arranque), são ignoradas e contadas.

registos do linuxptp e do chrony#

Estes cinco formatos leem o que um daemon de tempo em execução escreve sobre o seu próprio relógio. Servem para verificar uma cadeia de temporização a posteriori (um relógio de fronteira, o PHC de um grandmaster, um cliente chrony) com os mesmos estimadores que os outros registos. Não leem a configuração de um daemon, e nada aqui comunica com um daemon.

ptp4l, phc2sys, ts2phc: as linhas de servo do linuxptp, cada formato a ler apenas linhas do seu próprio programa. Uma leitura é uma linha da forma

ptp4l[5003.000]: master offset         40 s2 freq   +1480 path delay       497
phc2sys[7000.000]: CLOCK_REALTIME phc offset       -30 s2 freq    +100 delay   1200
ts2phc[8000.000]: /dev/ptp0 offset          3 s2 freq         -2
  • A marca temporal é o primeiro [seconds.fraction] da linha (o relógio monótono do daemon). Também é lida após um prefixo de syslog, onde um identificador de processo como ptp4l[812]: não tem fração e não é tomado.
  • A fase é o offset registado, em nanossegundos, convertido para segundos. É o erro de tempo medido pelo daemon do seu relógio escravo face à sua referência, tal como registado: positivo quando o escravo está adiantado. É o erro que resta sob controlo do servo, não a deriva de um relógio em marcha livre.
  • As palavras entre a marca temporal e offset nomeiam a fonte (master, eth0 master para um prefixo [eth0], CLOCK_REALTIME phc, /dev/ptp0). Um registo com mais do que uma fonte precisa de clock = "<that text>"; o erro lista-as.
  • As leituras anteriores à primeira vez em que o servo reporta s2 (bloqueado) são excluídas e contadas em n_skipped_lines: s0 e s1 são os estados desbloqueado e de salto, cujos desvios são transitórios de entrada. Um servo que nunca atinge s2 é recusado. Uma linha sem campo de estado é lida tal como está.
  • As linhas de resumo (rms ... max ...), as mensagens delay e selected best master e as linhas de outros programas são ignoradas e contadas.
  • As marcas temporais que andam para trás (um daemon reiniciado) são recusadas; divida o registo.

chrony-tracking, chrony-statistics: os ficheiros log tracking e log statistics do chrony, lidos por posição de coluna. Uma leitura é uma linha com pelo menos 14 colunas (tracking) ou 13 (statistics) que começa por uma data e hora UTC YYYY-MM-DD HH:MM:SS. A linha de cabeçalho das colunas é ignorada e contada; a linha ==== por baixo dela é ignorada sem ser contada.

  • Tracking: coluna 7, o desvio local na atualização do relógio, em segundos. O endereço IP ou o identificador de referência muda com a fonte selecionada, pelo que, sem clock, cada linha é lida como um único relógio local. clock = "<id>" mantém um identificador de referência.
  • Statistics: coluna 5, o desvio estimado de uma fonte, em segundos. Há uma série por endereço de fonte, e o registo precisa de clock = "<address>" quando contém mais do que uma.
  • As épocas são segundos desde 1980-01-06 00:00:00 UTC, sem tratamento de segundos intercalares. O chrony escreve uma linha por atualização ou por amostra de fonte, pelo que o espaçamento não é uniforme. tau0 é o espaçamento mediano; uma leitura a menos de meio tau0 da anteriormente mantida é descartada e contada em n_duplicates, e um espaçamento maior é uma lacuna, que gaps = "refuse" reporta. Indique tau0_s e gaps = "linear" para um registo com um intervalo de sondagem estável.

As colunas do chrony e as disposições de linha do linuxptp são as da documentação pública dos daemons. Os ficheiros de apoio em tests/fixtures/clock_log/linuxptp_chrony/ foram escritos para o Kshana com valores inventados (ver o seu NOTICE.md); nenhum registo real foi lido, pelo que uma disposição que difira entre versões do daemon ainda pode ser recusada ou mal lida. Uma linha que não corresponda é ignorada e contada, nunca adivinhada.

tau0 e lacunas#

Quando o registo transporta marcas temporais e não é indicado tau0, tau0 é o espaçamento mediano das marcas temporais consecutivas, arredondado a quatro algarismos significativos, e a fonte é reportada como median-spacing. O espaçamento de um contador difere do nominal pelo desvio de frequência da referência, partes em 10^6 ou menos. Um tau0_s no cenário prevalece sempre (fonte input), seguido de um comentário de cabeçalho tau0 (fonte header).

As amostras são colocadas na grelha t0 + i·tau0, e uma época em falta é uma lacuna. As leituras a mais de 1 % de tau0 fora da grelha são descartadas e contadas, tal como as duplicadas (mantém-se a primeira). A política de lacunas é uma das seguintes:

  • refuse (a predefinição): qualquer lacuna é um erro que conta as lacunas;
  • longest: manter o troço sem lacunas mais longo;
  • linear: preencher as lacunas interiores por interpolação linear e reportar o número preenchido.

Os estimadores precisam de um registo sem lacunas, razão pela qual as lacunas são resolvidas aqui.

O seu próprio relógio#

Uma tabela [clock_log] no tipo de cenário de relógio indica quão estável foi o seu próprio relógio, ao lado da simulação: scenarios/clock-measured-log.toml (kshana example clock-measured-log) é clock-holdover.toml com um excerto de 96 leituras de um relógio de satélite do IGS como um registo TimeLab embutido. Substitua text por path e format para o seu próprio ficheiro. O bloco measured no resultado contém como o registo foi lido (formato, tau0 e a origem, cada lacuna) e as suas ADEV, TDEV e MTIE; ele não altera a simulação.

Conduzir o holdover com o seu próprio relógio: [clock_fit]#

[clock_log]                      # the measured series, as above
format = "ticc"
path = "my-clock.txt"
channel = "chA"

[clock_fit]
replaces = "classical"           # or "quantum": the simulated clock whose noise the log replaces

O registo é ajustado com o procedimento de cartão de dispositivo de src/clock_library/card.rs (condicionamento, remoção do termo quadrático, identificação do ruído de desfasamento 1, mínimos quadrados ponderados em PM branco, FM branco, FM de cintilação e FM de passeio aleatório nos tempos de média com pelo menos 30 graus de liberdade). O relógio nomeado passa então a usar q_wf = h_0 / 2, q_rw = 2 pi^2 h_-2, flicker_floor = sqrt(2 ln 2 h_-1) e o drift ajustado; y0 permanece como está no cenário, porque um registo traz o deslocamento da sua referência, e não o do relógio após a disciplina. O ruído de fase branco é ajustado e indicado, mas não simulado. O resultado ganha um bloco fitted (os coeficientes, os pontos de ajuste, os valores usados pela execução, o que foi deixado de fora, o SHA-256 do registo) e o relógio recebe o id measured:<12 hex of the phase hash>. Com runs > 1 o conjunto sorteia a partir do relógio ajustado (o bloco measured exige runs = 1). Um ajuste sem ruído de frequência, um registo curto demais para ajustar e um replaces diferente de quantum ou classical são erros que o dizem. scenarios/clock-fitted-log.toml é um exemplo (6 horas de um relógio de satélite do IGS).

O que a comparação com ruído conhecido (tests/fixtures/clock_fit/RESULTS.md) mostra e o que se deve ter em mente:

  • Atingido: o nível de FM branco é recuperado dentro de 5 % em todo registo sintético que o tem; o cartão ajustado reproduz o desvio de Allan verdadeiro dentro de um fator de 1,35 em todo tempo de média em que foi ajustado; o expoente de ruído que o ajuste identifica é igual ao do allantools em todos os pontos (no registo 5071A, depois que o salto de fase que o condicionamento remove é removido também da entrada do allantools).
  • Não atingido, e fixado pelo teste: o FM de passeio aleatório só é recuperado quando domina os maiores tempos de média do registo e, mesmo assim, num de três registos de uma série de 131 072 s com cruzamento em 3 000 s, o ajuste atribuiu-o ao FM de cintilação e à deriva. A divisão entre FM de passeio aleatório e FM de cintilação não é fiável a partir de um único registo. A execução reproduz a estabilidade do registo nos tempos de média que o registo cobre; além deles as duas escolhas divergem (o FM de cintilação é um piso constante, o FM de passeio aleatório cresce com a raiz quadrada do tempo de média).
  • MODELLED: um cenário hipotético para o ruído desse relógio como o registo o mostra, não uma calibração do relógio e não uma previsão do seu comportamento futuro.

Um registo malformado é um erro que nomeia o que foi encontrado (a linha, a versão, o seletor ausente), nunca um resultado parcial: tests/clock_log_real_allantools.rs fixa 24 desses casos.

Evidências#

MODELLED. Este é um analisador, e a sua saída alimenta estimadores que são validados em outro local face ao allantools. Os testes unitários de src/clock_log.rs usam pequenos registos escritos à mão e, para os formatos linuxptp e chrony, os ficheiros de teste de tests/fixtures/clock_log/linuxptp_chrony/. tests/clock_log_allantools.rs executa a comparação fixada antecipadamente em tests/fixtures/clock_log/PREREGISTRATION.md: três registos sintéticos com semente, um por formato, relidos por um leitor independente escrito a partir desta página pelo mesmo autor, com as ADEV, TDEV e MTIE verificadas face ao allantools 2024,6; essa comparação cobre apenas os três primeiros formatos, e os leitores de linuxptp e chrony têm testes de analisador, mas nenhuma comparação com referência independente. Os registos dessa comparação são sintéticos, portanto nada ali descreve um relógio ou contador real; a comparação com séries medidas é descrita abaixo.

Com dados medidos#

tests/clock_log_real_allantools.rs executa a comparação fixada antecipadamente em tests/fixtures/clock_log_real/PREREGISTRATION.md (versionada antes de qualquer ficheiro de teste ou execução) em quatro séries medidas: o PHASE.DAT do Stable32, as primeiras 65 536 leituras de um relógio de césio 5071A contra um maser de hidrogénio, e os relógios do satélite G01 do IGS (30 s) e da estação ABMF (300 s) a partir do relógio final do IGS de 2026-08-02, como um recorte incorporado com o seu NOTICE. Os dois primeiros não têm concessão de redistribuição: os registos escritos a partir deles estão em realdata-cache/, ignorado pelo git (scripts/gen_clock_log_real_ref.py), e o teste di-lo e passa quando estão ausentes, a menos que KSHANA_REQUIRE_REALDATA=1. Cada registo é lido pelo motor e por um leitor independente, e ADEV, TDEV e MTIE são comparados com o allantools 2024,6. Registado em tests/fixtures/clock_log_real/RESULTS.md: no leitor distribuído, os registos TICC, a versão do cabeçalho e cinco mensagens de erro falharam nos limiares fixados antecipadamente; foram corrigidos e a comparação foi executada de novo sem alterações. Atingido, exceto um par: o MTIE de um registo de frequência difere do do allantools, porque o allantools integra a frequência menos a à sua média (fixado como NOT MET; a comparação em condições equivalentes é atingida). A linha permanece MODELLED: os registos TICC são dados de relógio medidos recodificados no formato do contador pelo nosso script (nenhuma captura TICC real foi encontrada), e o leitor de referência tem o mesmo autor que o do motor.