요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
ktime accessors
===============
Device drivers can read the current time using ktime_get() and the many
related functions declared in linux/timekeeping.h. As a rule of thumb,
using an accessor with a shorter name is preferred over one with a longer
name if both are equally fit for a particular use case.
Basic ktime_t based interfaces
------------------------------
The recommended simplest form returns an opaque ktime_t, with variants
that return time for different clock references:
.. c:function:: ktime_t ktime_get( void )
CLOCK_MONOTONIC
Useful for reliable timestamps and measuring short time intervals
accurately. Starts at system boot time but stops during suspend.
.. c:function:: ktime_t ktime_get_boottime( void )
CLOCK_BOOTTIME
Like ktime_get(), but does not stop when suspended. This can be
used e.g. for key expiration times that need to be synchronized
with other machines across a suspend operation.
.. c:function:: ktime_t ktime_get_real( void )
CLOCK_REALTIME
Returns the time in relative to the UNIX epoch starting in 1970
using the Coordinated Universal Time (UTC), same as gettimeofday()
user space. This is used for all timestamps that need to
persist across a reboot, like inode times, but should be avoided
for internal uses, since it can jump backwards due to a leap
second update, NTP adjustment settimeofday() operation from user
space.
.. c:function:: ktime_t ktime_get_clocktai( void )
CLOCK_TAI
Like ktime_get_real(), but uses the International Atomic Time (TAI)
reference instead of UTC to avoid jumping on leap second updates.
This is rarely useful in the kernel.
.. c:function:: ktime_t ktime_get_raw( void )
CLOCK_MONOTONIC_RAW
Like ktime_get(), but runs at the same rate as the hardware
clocksource without (NTP) adjustments for clock drift. This is
also rarely needed in the kernel.
nanosecond, timespec64, and second output
-----------------------------------------
For all of the above, there are variants that return the time in a
different format depending on what is required by the user:
.. 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 )
Same as the plain ktime_get functions, but returning a u64 number
of nanoseconds in the respective time reference, which may be
more convenient for some callers.
.. 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 * )
Same above, but returns the time in a 'struct timespec64', split
into seconds and nanoseconds. This can avoid an extra division
when printing the time, or when passing it into an external
interface that expects a 'timespec' or 'timeval' structure.
.. 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 )
Return a coarse-grained version of the time as a scalar
time64_t. This avoids accessing the clock hardware and rounds
down the seconds to the full seconds of the last timer tick
using the respective reference.
Coarse and fast_ns access
-------------------------
Some additional variants exist for more specialized cases:
.. 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 * )
These are quicker than the non-coarse versions, but less accurate,
corresponding to CLOCK_MONOTONIC_COARSE and CLOCK_REALTIME_COARSE
in user space, along with the equivalent boottime/tai/raw
timebase not available in user space.
The time returned here corresponds to the last timer tick, which
may be as much as 10ms in the past (for CONFIG_HZ=100), same as
reading the 'jiffies' variable. These are only useful when called
in a fast path and one still expects better than second accuracy,
but can't easily use 'jiffies', e.g. for inode timestamps.
Skipping the hardware clock access saves around 100 CPU cycles
on most modern machines with a reliable cycle counter, but
up to several microseconds on older hardware with an external
clocksource.
.. 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 )
These variants are safe to call from any context, including from
a non-maskable interrupt (NMI) during a timekeeper update, and
while we are entering suspend with the clocksource powered down.
This is useful in some tracing or debugging code as well as
machine check reporting, but most drivers should never call them,
since the time is allowed to jump under certain conditions.
Deprecated time interfaces
--------------------------
Older kernels used some other interfaces that are now being phased out
but may appear in third-party drivers being ported here. In particular,
all interfaces returning a 'struct timeval' or 'struct timespec' have
been replaced because the tv_sec member overflows in year 2038 on 32-bit
architectures. These are the recommended replacements:
.. c:function:: void ktime_get_ts( struct timespec * )
Use ktime_get() or ktime_get_ts64() instead.
.. 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() is a direct replacement, but consider using
monotonic time (ktime_get_ts64()) and/or a ktime_t based 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 )
These are replaced by ktime_get_coarse_real_ts64() and
ktime_get_coarse_ts64(). However, A lot of code that wants
coarse-grained times can use the simple 'jiffies' instead, while
some drivers may actually want the higher resolution accessors
these days.
.. 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 )
These are replaced by ktime_get_raw()/ktime_get_raw_ts64(),
ktime_get_clocktai()/ktime_get_clocktai_ts64() as well
as ktime_get_boottime()/ktime_get_boottime_ts64().
However, if the particular choice of clock source is not
important for the user, consider converting to
ktime_get()/ktime_get_ts64() instead for consistency.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
ktime 접근자
1-8ktime 접근자
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-96Nanosecond, `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-144Coarse 및 `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()`로 전환하는 방안을 검토하십시오.
요약과 해설
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` 기반 접근자로 교체해야 합니다.