UNIX 시간은 UNIX를 실행하는 컴퓨터에서 측정됩니다.
이 답변은 UTC (Coördinated Universal Time), TAI (International Atomic Time) 및 SI 초가 무엇인지 알기를 기대합니다. 그것들을 설명하는 것은 Unix와 Linux Stack Exchange의 범위를 넘어선 것입니다 . 이것은 물리학 또는 천문학 스택 교환 이 아닙니다 .
하드웨어
컴퓨터에는 시계와 타이머를 구동하는 다양한 발진기가 있습니다. 정확하게는 아키텍처에 따라 컴퓨터마다 다릅니다. 그러나 일반적으로 매우 일반적인 용어는 다음과 같습니다.
- 가 주기적 타이머 진동의 특정 번호를 카운트하고, 중앙 처리 장치에 인터럽트를 트리거하도록 프로그램 될 수있다 (PIT)은 대체로.
- 중앙 프로세서에는 실행되는 각 명령주기마다 1을 계산 하는 주기 카운터 가 있습니다.
매우 광범위한 용어로 작동 이론
운영 체제 커널은 PIT를 사용하여 틱 을 생성 합니다. PIT를 프리 런으로 설정하여 100 분의 1 초의 시간 간격 동안 올바른 진동 수를 세고 인터럽트를 생성 한 다음 카운트를 자동으로 재설정하여 다시 가도록합니다. 이에 대한 변형이 있지만 본질적 으로 고정 주파수 로 틱 인터럽트가 발생합니다.
소프트웨어에서 커널은 틱마다 카운터를 증가시킵니다. PIT를 처음부터 프로그래밍했기 때문에 틱 주파수를 알고 있습니다. 따라서 1 초에 몇 개의 진드기가 구성되는지 알고 있습니다. 이를 사용하여 초를 세는 카운터를 언제 증가시켜야하는지 알 수 있습니다. 후자는 커널의 "UNIX Time"에 대한 아이디어입니다. 실제로 자체 장치에 남겨두면 SI 초 당 하나의 속도로 단순히 위로 계산합니다.
네 가지가 이것을 복잡하게 만듭니다. 저는 이것을 매우 일반적인 용어로 표현하려고합니다.
하드웨어가 완벽하지 않습니다. 데이터 시트에 발진기 주파수가 N Hertz 라고 말하고있는 PIT 는 대신 N .00002 Hertz 의 주파수를 가질 수 있으며, 결과는 명백합니다.
이 체계는 CPU가 변수의 숫자를 증가시키기 위해 초당 수백 번 깨우기 때문에 전원 관리와 매우 나쁘게 상호 운용됩니다. 따라서 일부 운영 체제는 "틱없는"디자인으로 알려져 있습니다. PIT가 모든 틱에 대해 인터럽트를 보내도록하는 대신, 커널은 (낮은 레벨 스케줄러에서) 스레드 퀀텀이 없어도 틱이 몇 개나 진행되는지, PIT를 프로그래밍하여 틱을 계산합니다. 틱 인터럽트를 발행하기 전에 미래. 그러면 1 틱 대신 다음 틱 인터럽트에서 N 틱 의 통과를 기록해야한다는 것을 알고 있습니다.
응용 프로그램 소프트웨어는 커널의 현재 시간을 변경할 수 있습니다. 이 수 단계 값을하거나 수행 할 수 있습니다 죽이고 값을. 선회는 초 카운터를 증가시키기 위해 틱 수를 조정하는 것과 관련이 있습니다. 초 그래서 카운터 반드시 두 번째 SI 당 하나의 비율로 계산하지 않습니다 어쨌든 , 심지어 완벽한 오실레이터 가정. 스테핑은 초 카운터에 단순히 새로운 숫자를 작성하는 것과 관련이 있으며, 마지막 초가 넘어간 후 1 SI 초까지는 발생하지 않습니다.
최신 커널은 초뿐만 아니라 나노초도 계산합니다. 그러나 1 초에 한 번 틱 인터럽트가 발생하는 것은 말도 안되며 종종 불가능합니다. 이곳은 사이클 카운터 와 같은 것들이 작용하는 곳 입니다. 커널은 1 초마다 (또는 각 틱마다) 사이클 카운터 값을 기억하고, 나노초 단위의 시간을 알고 자하는 카운터 의 현재 값에서 마지막 1 초 이후 경과 된 나노초 수를 계산할 수 있습니다. 진드기). 그러나 전원 및 열 관리는 명령주기 주파수가 변경 될 수 있기 때문에 이로 인해 혼란을 겪습니다. 따라서 커널은 HPET (고정밀 이벤트 타이머)와 같은 추가 하드웨어에 의존하는 것과 같은 일을합니다.
C 언어와 POSIX
C 언어의 표준 라이브러리는 은폐 형의 측면에서 시간을 설명 time_t
하는 구조 타입 tm
다양한 특정 필드와 같은 다양한 라이브러리 함수 time()
, mktime()
, 및 localtime()
.
간단히 말해서 C 언어 자체time_t
는 사용 가능한 숫자 데이터 유형 중 하나이며 시간 차이를 계산하는 신뢰할 수있는 유일한 방법은 difftime()
함수 라는 것을 보증 합니다. POSIX 표준 time_t
은 실제로 정수 유형 중 하나이며 Epoch 이후 초를 세는 엄격한 보증을 제공합니다 . timespec
구조 유형 을 지정하는 것도 POSIX 표준입니다 .
time()
기능은 때때로 시스템 호출로 설명되어 있습니다. 사실, 그것은 오늘날 많은 시스템에서 기본 시스템 호출이 아니 었습니다. 예를 들어 FreeBSD에서 기본 시스템 호출은입니다 clock_gettime()
. 여기에는 다양한 방법으로 초 또는 초 + 나노초 단위로 측정 할 수있는 다양한 "시계"가 있습니다. 응용 프로그램 소프트웨어가 커널에서 UNIX 시간을 읽는 것은이 시스템 호출입니다. (일치하는 clock_settime()
시스템 호출을 통해 단계를 수행하고 adjtime()
시스템 호출을 통해 시스템을 종료 할 수 있습니다.)
많은 사람들이 POSIX 표준을 규정하는 것에 대해 매우 명확하고 정확한 주장으로 흔들어 놓습니다. 그러한 사람들은 종종 POSIX 표준을 실제로 읽지 않습니다 . 이론적 근거에서 알 수 있듯이 표준에서 사용하는 "에 포치 이후의 초"를 세는 아이디어는 의도적으로 POSIX 초가 SI 초와 길이가 같거나 결과 gmtime()
가 "필수적으로"라고 지정하지 않습니다. 모양에도 불구하고 UTC ". POSIX 표준은 의도적으로관리자가 가서 일주일 후 시계를 재설정하여 윤초 조정을 수동으로 수정하는 UNIX 시스템을 허용 할 정도로 충분히 느슨합니다. 실제로, 근거는 시계 가 현재 UTC 시간 이외의 시간 으로 의도적으로 잘못 설정된 시스템을 수용하기에 의도적으로 느슨하다고 지적합니다 .
UTC와 TAI
커널에서 얻은 UNIX 시간 해석은 응용 프로그램에서 실행되는 라이브러리 루틴에 달려 있습니다. POSIX는 커널 시간과 "중단 시간"사이의 ID를 지정합니다 struct tm
. 그러나 Daniel J. Bernstein이 한 번 지적했듯이 1997 년판 표준은이 정체성을 난처하게 잘못 이해하여 Gregorian Calendar의 윤년 규칙 (학생들이 배우는 것)을 어지럽게하여 2100 년부터 계산에 오류가 발생했습니다. "관념보다 위반에 더 영광이된다"는 마음에 떠오른 문구입니다.
그리고 실제로 그렇습니다. 오늘날 몇몇 시스템은 Arthur David Olson이 작성한 라이브러리 루틴을 기반으로이 해석을 기반으로하며, 일반적으로 아래의 데이터베이스 파일로 인코딩 된 악명 높은 "올슨 시간대 데이터베이스"를 참조합니다 /usr/share/zoneinfo/
. Olson 시스템에는 두 가지 모드가 있습니다.
- 커널의 "Epoch 이후 초"는 윤초를 제외하고 1970-01-01 00:00:00 UTC 이후 UTC 초를 계산하는 것으로 간주됩니다. 이것은
posix/
Olson 시간대 데이터베이스 파일 세트를 사용 합니다. 모든 날에는 86400 커널 초가 있으며 분당 61 초는 아니지만 항상 SI 초의 길이는 아니며 윤초가 발생할 때 커널 시계가 회전하거나 스테핑해야합니다.
- 커널의 "Epoch 이후의 초"는 1970-01-01 00:00:10 TAI 이후의 TAI 초를 계산하는 것으로 간주됩니다. 이것은
right/
Olson 시간대 데이터베이스 파일 세트를 사용 합니다. 커널 초의 길이는 1 SI 초이며 커널 시계는 윤초를 조정하기 위해 회전 또는 스테핑을 할 필요가 없지만 고장 시간은 23:59:60과 같은 값을 가질 수 있으며 일이 항상 86400 커널 초인 것은 아닙니다.
M. Bernstein은 도구 daemontools
세트를 포함하여 1970-01-01 00:00:00 TAI 이후 TAI 초를 얻기 위해 right/
10을 추가했기 때문에 필요한 여러 도구를 작성했습니다 time_t
. 그는 이것을 매뉴얼 페이지에 문서화했습니다.
이 요구 사항은 (아마도 무의식적으로) 등의 툴 세트에 의해 상속 daemontools-encore
및 runit
펠릭스 폰 Leitner의의에 의해 libowfat
. 사용 번스타인multilog
, 귄터multilog
, 또는 파페svlogd
올슨과 posix/
구성, 예를 들어, 그리고 TAI64N 타임 스탬프 모두가 뒤에 26초 (이 글을 쓰는 시점에서)입니다 실제 번째 1970-01-01 0시 0분 10초부터 계산 TAI를 타이.
Laurent Bercot와 나는 우리가 다른 접근법을 취했지만 s6와 nosh에서 이것을 해결했습니다. M. Bercot tai_from_sysclock()
는 컴파일 타임 플래그에 의존합니다. 상기 TAI64N 모양의 거래 것을 요기 도구 TZ
와 TZDIR
에 대한 환경 변수를 자동 감지 posix/
하고 right/
그들이 할 수있는 경우.
흥미롭게도 FreeBSD 문서 time2posix()
와 posix2time()
함수는 Olson right/
모드와 동등한 time_t
TAI 초 를 허용합니다 . 그러나 분명히 가능하지는 않습니다.
다시 한번…
UNIX 시간은 컴퓨터 하드웨어에 포함 된 발진기에 의해 UNIX를 실행하는 컴퓨터에서 측정됩니다. SI 초를 사용하지 않습니다. 피상적으로 비슷하더라도 UTC가 아닙니다. 그것은 의도적으로 잘못된 당신의 시계를 허용합니다.
추가 자료