← Documents Documentation/core-api/timekeeping.rst GitHub 원문 ↗

Linux 6.18.37 · Core API

ktime accessors

Kernel driver가 목적에 맞는 ktime clock reference, 반환 형식, coarse 또는 NMI-safe 접근자를 선택하고 오래된 time interface를 교체하는 방법을 설명합니다.

Source pathDocumentation/core-api/timekeeping.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

timekeeping.rst:1-190

경과 시간과 interval 측정에는 보통 `CLOCK_MONOTONIC` 계열을 사용하고, suspend 시간까지 포함하려면 `CLOCK_BOOTTIME`, reboot 후에도 의미가 있는 wall-clock timestamp에는 `CLOCK_REALTIME`을 선택합니다.

반환 형식은 opaque `ktime_t`, nanosecond 단위 `u64`, second와 nanosecond를 나눈 `timespec64`, coarse-grained `time64_t` 중 caller의 계산과 외부 interface 요구에 맞춰 선택합니다.

Coarse 접근자는 hardware clock read 비용을 줄이는 대신 마지막 timer tick 수준의 정확도만 제공합니다. `fast_ns` 접근자는 NMI와 suspend 진입 중에도 호출할 수 있지만 시간이 뛸 수 있어 일반 driver 용도에는 적합하지 않습니다.

32-bit에서 2038년 overflow가 발생하는 `timeval` 및 구형 `timespec` API는 `ktime_t` 또는 `timespec64` 기반 접근자로 교체해야 합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ktime accessors
2 ===============
3
4 Device drivers can read the current time using ktime_get() and the many
5 related functions declared in linux/timekeeping.h. As a rule of thumb,
6 using an accessor with a shorter name is preferred over one with a longer
7 name if both are equally fit for a particular use case.
8
9 Basic ktime_t based interfaces
10 ------------------------------
11
12 The recommended simplest form returns an opaque ktime_t, with variants
13 that return time for different clock references:
14
15
16 .. c:function:: ktime_t ktime_get( void )
17
18 CLOCK_MONOTONIC
19
20 Useful for reliable timestamps and measuring short time intervals
21 accurately. Starts at system boot time but stops during suspend.
22
23 .. c:function:: ktime_t ktime_get_boottime( void )
24
25 CLOCK_BOOTTIME
26
27 Like ktime_get(), but does not stop when suspended. This can be
28 used e.g. for key expiration times that need to be synchronized
29 with other machines across a suspend operation.
30
31 .. c:function:: ktime_t ktime_get_real( void )
32
33 CLOCK_REALTIME
34
35 Returns the time in relative to the UNIX epoch starting in 1970
36 using the Coordinated Universal Time (UTC), same as gettimeofday()
37 user space. This is used for all timestamps that need to
38 persist across a reboot, like inode times, but should be avoided
39 for internal uses, since it can jump backwards due to a leap
40 second update, NTP adjustment settimeofday() operation from user
41 space.
42
43 .. c:function:: ktime_t ktime_get_clocktai( void )
44
45 CLOCK_TAI
46
47 Like ktime_get_real(), but uses the International Atomic Time (TAI)
48 reference instead of UTC to avoid jumping on leap second updates.
49 This is rarely useful in the kernel.
50
51 .. c:function:: ktime_t ktime_get_raw( void )
52
53 CLOCK_MONOTONIC_RAW
54
55 Like ktime_get(), but runs at the same rate as the hardware
56 clocksource without (NTP) adjustments for clock drift. This is
57 also rarely needed in the kernel.
58
59 nanosecond, timespec64, and second output
60 -----------------------------------------
61
62 For all of the above, there are variants that return the time in a
63 different format depending on what is required by the user:
64
65 .. c:function:: u64 ktime_get_ns( void )
66 u64 ktime_get_boottime_ns( void )
67 u64 ktime_get_real_ns( void )
68 u64 ktime_get_clocktai_ns( void )
69 u64 ktime_get_raw_ns( void )
70
71 Same as the plain ktime_get functions, but returning a u64 number
72 of nanoseconds in the respective time reference, which may be
73 more convenient for some callers.
74
75 .. c:function:: void ktime_get_ts64( struct timespec64 * )
76 void ktime_get_boottime_ts64( struct timespec64 * )
77 void ktime_get_real_ts64( struct timespec64 * )
78 void ktime_get_clocktai_ts64( struct timespec64 * )
79 void ktime_get_raw_ts64( struct timespec64 * )
80
81 Same above, but returns the time in a 'struct timespec64', split
82 into seconds and nanoseconds. This can avoid an extra division
83 when printing the time, or when passing it into an external
84 interface that expects a 'timespec' or 'timeval' structure.
85
86 .. c:function:: time64_t ktime_get_seconds( void )
87 time64_t ktime_get_boottime_seconds( void )
88 time64_t ktime_get_real_seconds( void )
89 time64_t ktime_get_clocktai_seconds( void )
90 time64_t ktime_get_raw_seconds( void )
91
92 Return a coarse-grained version of the time as a scalar
93 time64_t. This avoids accessing the clock hardware and rounds
94 down the seconds to the full seconds of the last timer tick
95 using the respective reference.
96
97 Coarse and fast_ns access
98 -------------------------
99
100 Some additional variants exist for more specialized cases:
101
102 .. c:function:: ktime_t ktime_get_coarse( void )
103 ktime_t ktime_get_coarse_boottime( void )
104 ktime_t ktime_get_coarse_real( void )
105 ktime_t ktime_get_coarse_clocktai( void )
106
107 .. c:function:: u64 ktime_get_coarse_ns( void )
108 u64 ktime_get_coarse_boottime_ns( void )
109 u64 ktime_get_coarse_real_ns( void )
110 u64 ktime_get_coarse_clocktai_ns( void )
111
112 .. c:function:: void ktime_get_coarse_ts64( struct timespec64 * )
113 void ktime_get_coarse_boottime_ts64( struct timespec64 * )
114 void ktime_get_coarse_real_ts64( struct timespec64 * )
115 void ktime_get_coarse_clocktai_ts64( struct timespec64 * )
116
117 These are quicker than the non-coarse versions, but less accurate,
118 corresponding to CLOCK_MONOTONIC_COARSE and CLOCK_REALTIME_COARSE
119 in user space, along with the equivalent boottime/tai/raw
120 timebase not available in user space.
121
122 The time returned here corresponds to the last timer tick, which
123 may be as much as 10ms in the past (for CONFIG_HZ=100), same as
124 reading the 'jiffies' variable. These are only useful when called
125 in a fast path and one still expects better than second accuracy,
126 but can't easily use 'jiffies', e.g. for inode timestamps.
127 Skipping the hardware clock access saves around 100 CPU cycles
128 on most modern machines with a reliable cycle counter, but
129 up to several microseconds on older hardware with an external
130 clocksource.
131
132 .. c:function:: u64 ktime_get_mono_fast_ns( void )
133 u64 ktime_get_raw_fast_ns( void )
134 u64 ktime_get_boot_fast_ns( void )
135 u64 ktime_get_tai_fast_ns( void )
136 u64 ktime_get_real_fast_ns( void )
137
138 These variants are safe to call from any context, including from
139 a non-maskable interrupt (NMI) during a timekeeper update, and
140 while we are entering suspend with the clocksource powered down.
141 This is useful in some tracing or debugging code as well as
142 machine check reporting, but most drivers should never call them,
143 since the time is allowed to jump under certain conditions.
144
145 Deprecated time interfaces
146 --------------------------
147
148 Older kernels used some other interfaces that are now being phased out
149 but may appear in third-party drivers being ported here. In particular,
150 all interfaces returning a 'struct timeval' or 'struct timespec' have
151 been replaced because the tv_sec member overflows in year 2038 on 32-bit
152 architectures. These are the recommended replacements:
153
154 .. c:function:: void ktime_get_ts( struct timespec * )
155
156 Use ktime_get() or ktime_get_ts64() instead.
157
158 .. c:function:: void do_gettimeofday( struct timeval * )
159 void getnstimeofday( struct timespec * )
160 void getnstimeofday64( struct timespec64 * )
161 void ktime_get_real_ts( struct timespec * )
162
163 ktime_get_real_ts64() is a direct replacement, but consider using
164 monotonic time (ktime_get_ts64()) and/or a ktime_t based interface
165 (ktime_get()/ktime_get_real()).
166
167 .. c:function:: struct timespec current_kernel_time( void )
168 struct timespec64 current_kernel_time64( void )
169 struct timespec get_monotonic_coarse( void )
170 struct timespec64 get_monotonic_coarse64( void )
171
172 These are replaced by ktime_get_coarse_real_ts64() and
173 ktime_get_coarse_ts64(). However, A lot of code that wants
174 coarse-grained times can use the simple 'jiffies' instead, while
175 some drivers may actually want the higher resolution accessors
176 these days.
177
178 .. c:function:: struct timespec getrawmonotonic( void )
179 struct timespec64 getrawmonotonic64( void )
180 struct timespec timekeeping_clocktai( void )
181 struct timespec64 timekeeping_clocktai64( void )
182 struct timespec get_monotonic_boottime( void )
183 struct timespec64 get_monotonic_boottime64( void )
184
185 These are replaced by ktime_get_raw()/ktime_get_raw_ts64(),
186 ktime_get_clocktai()/ktime_get_clocktai_ts64() as well
187 as ktime_get_boottime()/ktime_get_boottime_ts64().
188 However, if the particular choice of clock source is not
189 important for the user, consider converting to
190 ktime_get()/ktime_get_ts64() instead for consistency.
191

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

ktime 접근자

1-8

ktime 접근자

Device driver는 `ktime_get()`과 `linux/timekeeping.h`에 선언된 여러 관련 function으로 현재 시간을 읽을 수 있습니다. 경험 법칙상 특정 use case에 두 접근자가 똑같이 적합하다면 이름이 더 짧은 접근자를 사용하는 것이 좋습니다.

기본 ktime_t 기반 interface

9-58

기본 `ktime_t` 기반 interface

가장 단순하고 권장되는 형태는 opaque `ktime_t`를 반환하며, 서로 다른 clock reference의 시간을 반환하는 variant가 있습니다.

.. c:function:: ktime_t ktime_get( void )

`CLOCK_MONOTONIC`

신뢰할 수 있는 timestamp와 짧은 시간 간격의 정확한 측정에 유용합니다. System boot 시점에 시작하지만 suspend 중에는 진행을 멈춥니다.

.. c:function:: ktime_t ktime_get_boottime( void )

`CLOCK_BOOTTIME`

`ktime_get()`과 비슷하지만 suspend 상태에서도 멈추지 않습니다. 예를 들어 suspend operation을 거쳐 다른 machine과 동기화되어야 하는 key expiration time에 사용할 수 있습니다.

.. c:function:: ktime_t ktime_get_real( void )

`CLOCK_REALTIME`

1970년에 시작하는 UNIX epoch 기준 시간을 사용자 공간의 `gettimeofday()`와 마찬가지로 Coordinated Universal Time(UTC)으로 반환합니다. Inode time처럼 reboot 후에도 유지되어야 하는 모든 timestamp에 사용합니다. 그러나 leap second update, NTP adjustment 또는 사용자 공간의 `settimeofday()` operation 때문에 시간이 뒤로 뛸 수 있으므로 kernel 내부 용도로는 피해야 합니다.

.. c:function:: ktime_t ktime_get_clocktai( void )

`CLOCK_TAI`

`ktime_get_real()`과 비슷하지만 leap second update 때 시간이 뛰는 것을 피하도록 UTC 대신 International Atomic Time(TAI) reference를 사용합니다. Kernel에서 유용한 경우는 드뭅니다.

.. c:function:: ktime_t ktime_get_raw( void )

`CLOCK_MONOTONIC_RAW`

`ktime_get()`과 비슷하지만 clock drift에 대한 NTP adjustment 없이 hardware clocksource와 같은 속도로 진행합니다. Kernel에서 필요한 경우는 역시 드뭅니다.

Nanosecond, timespec64 및 second 출력

59-96

Nanosecond, `timespec64` 및 second 출력

위 접근자에는 caller가 요구하는 형식에 따라 시간을 다른 형태로 반환하는 variant가 있습니다.

.. c:function:: u64 ktime_get_ns( void )
                u64 ktime_get_boottime_ns( void )
                u64 ktime_get_real_ns( void )
                u64 ktime_get_clocktai_ns( void )
                u64 ktime_get_raw_ns( void )

기본 `ktime_get` function과 같지만 해당 time reference의 nanosecond 수를 `u64`로 반환합니다. 일부 caller에는 이 형식이 더 편리할 수 있습니다.

.. c:function:: void ktime_get_ts64( struct timespec64 * )
                void ktime_get_boottime_ts64( struct timespec64 * )
                void ktime_get_real_ts64( struct timespec64 * )
                void ktime_get_clocktai_ts64( struct timespec64 * )
                void ktime_get_raw_ts64( struct timespec64 * )

위와 같지만 시간을 second와 nanosecond로 나눈 `struct timespec64`에 반환합니다. 시간을 출력할 때 별도의 division을 피할 수 있고, `timespec` 또는 `timeval` structure를 기대하는 외부 interface에 전달할 때도 유용합니다.

.. c:function:: time64_t ktime_get_seconds( void )
                time64_t ktime_get_boottime_seconds( void )
                time64_t ktime_get_real_seconds( void )
                time64_t ktime_get_clocktai_seconds( void )
                time64_t ktime_get_raw_seconds( void )

시간을 scalar `time64_t`로 나타낸 coarse-grained version을 반환합니다. Clock hardware 접근을 피하고, 각 reference에 따라 마지막 timer tick의 온전한 second 단위로 내림합니다.

Coarse 및 fast_ns 접근

97-144

Coarse 및 `fast_ns` 접근

더 특수한 상황을 위한 variant도 있습니다.

.. c:function:: ktime_t ktime_get_coarse( void )
                ktime_t ktime_get_coarse_boottime( void )
                ktime_t ktime_get_coarse_real( void )
                ktime_t ktime_get_coarse_clocktai( void )
.. c:function:: u64 ktime_get_coarse_ns( void )
                u64 ktime_get_coarse_boottime_ns( void )
                u64 ktime_get_coarse_real_ns( void )
                u64 ktime_get_coarse_clocktai_ns( void )
.. c:function:: void ktime_get_coarse_ts64( struct timespec64 * )
                void ktime_get_coarse_boottime_ts64( struct timespec64 * )
                void ktime_get_coarse_real_ts64( struct timespec64 * )
                void ktime_get_coarse_clocktai_ts64( struct timespec64 * )

이 function들은 non-coarse version보다 빠르지만 정확도는 낮습니다. 사용자 공간의 `CLOCK_MONOTONIC_COARSE`와 `CLOCK_REALTIME_COARSE`에 해당하며, 사용자 공간에는 없는 동등한 boottime, TAI 및 raw timebase도 제공합니다.

여기서 반환하는 시간은 마지막 timer tick에 해당하므로 `CONFIG_HZ=100`에서는 최대 10ms 전의 값일 수 있으며, `jiffies` variable을 읽는 것과 같습니다. Fast path에서 호출되고 second보다 나은 정확도가 필요하지만 inode timestamp처럼 `jiffies`를 쉽게 사용할 수 없을 때만 유용합니다.

Hardware clock 접근을 생략하면 신뢰할 수 있는 cycle counter가 있는 대다수 최신 machine에서 약 100 CPU cycle을 절약하며, 외부 clocksource를 사용하는 구형 hardware에서는 최대 수 microsecond를 절약할 수 있습니다.

.. c:function:: u64 ktime_get_mono_fast_ns( void )
                u64 ktime_get_raw_fast_ns( void )
                u64 ktime_get_boot_fast_ns( void )
                u64 ktime_get_tai_fast_ns( void )
                u64 ktime_get_real_fast_ns( void )

이 variant는 timekeeper update 중의 non-maskable interrupt(NMI), 그리고 clocksource의 power가 내려간 suspend 진입 중을 포함한 모든 context에서 안전하게 호출할 수 있습니다. 일부 tracing 또는 debugging code와 machine check reporting에는 유용하지만, 특정 조건에서 시간이 뛸 수 있으므로 대부분의 driver는 호출해서는 안 됩니다.

사용 중단된 time interface

145-190

사용 중단된 time interface

구형 kernel은 현재 단계적으로 제거 중인 다른 interface를 사용했으며, 이 kernel로 porting하는 third-party driver에서 발견될 수 있습니다. 특히 `struct timeval` 또는 `struct timespec`을 반환하는 모든 interface는 32-bit architecture에서 `tv_sec` member가 2038년에 overflow하므로 교체되었습니다. 다음은 권장 replacement입니다.

.. c:function:: void ktime_get_ts( struct timespec * )

대신 `ktime_get()` 또는 `ktime_get_ts64()`를 사용하십시오.

.. c:function:: void do_gettimeofday( struct timeval * )
                void getnstimeofday( struct timespec * )
                void getnstimeofday64( struct timespec64 * )
                void ktime_get_real_ts( struct timespec * )

`ktime_get_real_ts64()`가 직접적인 replacement이지만, monotonic time인 `ktime_get_ts64()` 또는 `ktime_t` 기반 interface인 `ktime_get()`과 `ktime_get_real()`을 사용하는 방안도 검토하십시오.

.. c:function:: struct timespec current_kernel_time( void )
                struct timespec64 current_kernel_time64( void )
                struct timespec get_monotonic_coarse( void )
                struct timespec64 get_monotonic_coarse64( void )

이 function들은 `ktime_get_coarse_real_ts64()`와 `ktime_get_coarse_ts64()`로 교체되었습니다. 다만 coarse-grained time을 원하는 code 중 상당수는 단순한 `jiffies`를 사용할 수 있고, 일부 driver는 이제 더 높은 resolution의 접근자를 실제로 원할 수 있습니다.

.. c:function:: struct timespec getrawmonotonic( void )
                struct timespec64 getrawmonotonic64( void )
                struct timespec timekeeping_clocktai( void )
                struct timespec64 timekeeping_clocktai64( void )
                struct timespec get_monotonic_boottime( void )
                struct timespec64 get_monotonic_boottime64( void )

이 function들은 각각 `ktime_get_raw()`와 `ktime_get_raw_ts64()`, `ktime_get_clocktai()`와 `ktime_get_clocktai_ts64()`, 그리고 `ktime_get_boottime()`과 `ktime_get_boottime_ts64()`로 교체되었습니다.

그러나 특정 clock source 선택이 사용자에게 중요하지 않다면 일관성을 위해 `ktime_get()` 또는 `ktime_get_ts64()`로 전환하는 방안을 검토하십시오.