O Unix armazena o tempo como o número de segundos desde 1º de janeiro de 1970. E isso significa que o Linux também. Explicamos esse sistema aparentemente estranho e por que o dia do juízo final foi agendado para 2038.
Índice
A primeira época do Unix
Goethe ( 1749-1832 ) declarou “Cada segundo tem um valor infinito”. Isso é verdade, cada um de nós tem apenas alguns segundos aqui no planeta Terra, e não sabemos quando será o nosso último segundo. Mas sabemos nosso aniversário e quando nossa contagem regressiva mortal começou.
Unix – como a rainha britânica – faz dois aniversários. Ou, mais precisamente, houve duas ocasiões distintas em que começou a contar os segundos de sua existência. A primeira vez que o Unix começou a contar foi à meia-noite de 1º de janeiro de 1971.
Podemos ver isso claramente revisando uma seção da primeira edição do Unix Programmer’s Manual , datado de 3 de novembro de 1971. Role para baixo até a página 13 dessa seção e você verá uma descrição do time
comando (agora extinto) . Disseram-nos que ” time
retorna o tempo desde 00:00:00 de 1º de janeiro de 1971, medido em sessenta avos de segundo”.
Calendários e sistemas de tempo medem o tempo começando em algum ponto significativo no passado, como um evento cosmológico, a fundação de um império ou o sucesso de uma revolução. Em sistemas operacionais, uma hora e data arbitrárias são escolhidas como o ponto a partir do qual a contagem começa. Esta é a época desse sistema operacional.
O Unix usava um inteiro não assinado de 32 bits para manter a contagem de 60 segundos desde a época. Esta é uma variável numérica capaz de manter valores na faixa de 0 a 4.294.967.295 (2 32 −1). Isso parece ser muito. Mas o contador aumentou 60 vezes por segundo e, como aponta o Manual do Programador, “O usuário com mentalidade cronológica notará que 2 ** 32 sessenta avos de um segundo é apenas cerca de 2,5 anos.”
Com uma taxa de consumo de 60 números por segundo, o contador teria atingido seu valor máximo em 8 de abril de 1973, pouco menos de 829 dias depois.
A segunda época do Unix
Desnecessário dizer que isso foi resolvido rapidamente. O inteiro não assinado foi substituído por um inteiro assinado de 32 bits . Pode parecer uma escolha surpreendente porque um inteiro com sinal é capaz de conter um número menor de valores positivos – 2.147.483.647 (2 31 ) – do que um inteiro sem sinal. No entanto, a velocidade de consumo também foi reduzida de 60 segundos para segundos inteiros.
Leva mais tempo para contar de 0 a 2.147.483.647 contando um número por segundo do que para contar de 0 a 4.294.967.295 a 60 contagens por segundo. E por uma boa margem. O novo esquema não atingiria seu valor máximo por pouco mais de 68 anos. Isso parecia tão distante no futuro que a época foi restaurada para um ponto anterior no tempo. A nova época foi marcada para a meia-noite de 1º de janeiro de 1970, UTC.
Esse ponto, 68 anos no futuro, está agora irritantemente perto. Para ser mais preciso, chegaremos às 03:14:07 UTC em 19 de janeiro de 2038.
Um esquema simples, mas eficaz
Usar um único número inteiro para contar o número de intervalos de tempo a partir de um determinado ponto no tempo é uma maneira eficiente de armazenar o tempo. Você não precisa armazenar estruturas complicadas de anos, meses, dias e horários. e é independente de país, localidade e fuso horário.
Multiplicar o número no inteiro pelo tamanho do intervalo de tempo – neste caso, um segundo – dá a você o tempo desde a época, e converter disso para formatos específicos de local com ajustes de fuso horário é relativamente trivial.
No entanto, ele fornece um limite superior integrado. Mais cedo ou mais tarde, você atingirá o valor máximo que pode conter no tipo de variável escolhido. No momento em que este artigo foi escrito, o ano de 2038 estava apenas a 17 anos.
É semelhante, mas ligeiramente diferente do problema com os primeiros sistemas de computador do século passado, usando dois dígitos para armazenar anos. Quando o calendário avançou para o novo ano e novo século de 2000, um valor de ano armazenado como “00” seria interpretado como 2000 ou 1900?
Estima-se que a correção do chamado “ bug do milênio ” tenha custado aos Estados Unidos mais de US $ 100 bilhões e tenha levado milhares de homens-anos para ser resolvida globalmente. Houve alguns problemas nos primeiros dias de janeiro de 2000, mas nada como os desastres que teriam ocorrido se o bug tivesse sido ignorado.
Dia do Juízo Final Adiado
Como o Linux e todos os sistemas operacionais semelhantes ao Unix compartilham o mesmo problema, o problema do ano de 2038 foi levado a sério por algum tempo, com correções sendo adicionadas ao kernel desde 2014. Isso está em andamento com correções sendo adicionadas ao kernel recentemente, em janeiro .2020 para resolver o problema de inteiros de 32 bits.
Claro, um computador Linux funcional contém muito mais do que um kernel. Todos os utilitários operacionais e aplicativos de usuário que fazem uso do tempo do sistema por meio de várias APIs e interfaces precisam ser modificados para esperar valores de 64 bits. Os sistemas de arquivos também devem ser atualizados para aceitar carimbos de data / hora de 64 bits para arquivos e diretórios.
O Linux está em todo lugar . Uma falha catastrófica no Linux significaria falhas em todos os tipos de sistemas baseados em computador. O Linux executa a maior parte da web, a maior parte da nuvem pública e até mesmo espaçonaves. Administra casas inteligentes e carros autônomos. Os smartphones têm um kernel derivado do Unix em seu coração. Praticamente qualquer coisa – como firewalls de rede, roteadores e modems de banda larga – que possui sistemas operacionais embutidos rodam em Linux.
É ótimo que o Linux esteja prestes a ser consertado. Instalaremos as atualizações e pronto. Mas quais são as chances de que todos esses dispositivos sejam corrigidos e atualizados? Muitos deles nem mesmo estarão em serviço até lá, então será um ponto discutível, mas alguns ainda estarão desligando. Escondido em recantos escuros e empoeirados em salas de servidores e gabinetes de rack, talvez, mas eles estarão lá, trabalhando silenciosamente, enquanto os segundos se passam até cerca de três e quinze da manhã de 19 de janeiro de 2038.
Mas dispositivos como esse devem ser uma pequena minoria. A grande maioria dos sistemas verá o momento crítico chegar e ir sem incidentes. Mais uma vez, poderemos relaxar. Pelo menos, até a aproximação do ano 2.486, trazendo com ele exatamente o mesmo problema para sistemas que usam inteiros baseados em 64 bits para contar o tempo desde a época.
O comando de data
Podemos usar o date
comando para verificar se o Linux e outros derivados do Unix ainda usam o esquema simples e original de armazenar o valor do tempo como o número de segundos desde a época.
Usar o date
comando sem nenhum parâmetro imprime a data e hora atuais na janela do terminal. Também lhe é mostrado o fuso horário para o qual a hora está ajustada. EDT é Eastern Daylight Time, o que significa que nosso computador de teste está no Eastern Time Zone, e o horário de verão está em vigor. Quando o horário de verão não está em vigor, o fuso horário do leste usa o horário padrão do leste.
Para ver o valor inteiro subjacente, podemos usar uma string de formato de exibição. As strings de formato têm um sinal de mais “+” como primeiro caractere. O token de formato “% s” significa “mostrar os segundos desde a época”.
Se pegarmos o valor de segundos retornado por date
e alimentá-lo de volta para o date
comando com a opção -d
(tempo de exibição descrito por uma string), ele irá convertê-lo de volta para uma data e hora regulares.
encontro
data +% s
date -d @ 1633183955
Podemos mostrar que o valor inteiro realmente representa o tempo exibindo o número de segundos, dormindo por 10 segundos e mostrando o novo número de segundos. Os dois valores inteiros serão diferentes em exatamente 10.
data +% s && sono 10 && data +% s
Vimos que podemos passar alguns segundos para o date
comando e ele se converte em uma hora e data para nós. Se fizermos apenas isso usando zero segundo como entrada nosso valor, date
devemos imprimir a data e hora da época do Unix.
TZ = 'UTC' data -d @ 0 + '% x% R'
O comando se divide assim:
- TZ = ‘UTC’ : A época foi definida usando o Tempo Universal Coordenado (UTC, então precisamos informar
date
para usar o UTC. A construção “TZ =” define o fuso horário efetivo apenas para o comando atual. - data : o
date
comando. - -d @ 0 : Dizemos
date
para usar uma string como entrada, não a hora “agora”. A string que passamos contém zero segundos. - + ‘% x% R’ : A string de formato de saída. O token de formato “% x” informa
date
para exibir o ano, mês e dia. O token de formato “% R” instrui odate
uso do formato de 24 horas para as horas e minutos. Como há espaços na string de formato, colocamos toda a string entre aspas simples ”'
” para que a string seja tratada como um único item.
Como esperado, a saída é meia-noite de 1º de janeiro de 1970.
Até a próxima vez
Muitas vezes, o simples é o melhor. Contar segundos a partir de um dado fixo é a maneira mais simples de marcar a passagem do tempo. Mas o passar do tempo traz novos desafios. Com as correções implementadas, parece que chegamos ao ano de 2.486.
Acho que é seguro dizer que vamos nos preocupar com isso um pouco mais perto da hora.