Vin*_*ent 2 c linux glibc timespec c11
该C11标准规定的功能timespec_get。如果我在 cppreference 或我的计算机上运行示例代码,它会起作用:
#include <stdio.h>
#include <time.h>
int main(void)
{
struct timespec ts;
timespec_get(&ts, TIME_UTC);
char buff[100];
strftime(buff, sizeof buff, "%D %T", gmtime(&ts.tv_sec));
printf("Current time: %s.%09ld UTC\n", buff, ts.tv_nsec);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我在这里查看 glibc 的来源,代码如下:
#include <time.h>
/* Set TS to calendar time based in time base BASE. */
int
timespec_get (struct timespec *ts, int base)
{
switch (base)
{
case TIME_UTC:
/* Not supported. */
return 0;
default:
return 0;
}
return base;
}
stub_warning (timespec_get)
Run Code Online (Sandbox Code Playgroud)
哪个......不应该工作......
这就引出了一个问题:timespec_get实际调用的源代码在哪里?
该timespec_get函数的实现取决于运行库的系统,因此它既显示为存根time/timespec_get.c(如果没有实现可用),也显示为其他地方的各种依赖于系统的实现。
你可以在sysdeps/unix/sysv/linux/timespec_get.c, 中看到 Linux 实现
/* Set TS to calendar time based in time base BASE. */
int
timespec_get (struct timespec *ts, int base)
{
switch (base)
{
int res;
INTERNAL_SYSCALL_DECL (err);
case TIME_UTC:
res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, ts);
if (INTERNAL_SYSCALL_ERROR_P (res, err))
return 0;
break;
default:
return 0;
}
return base;
}
Run Code Online (Sandbox Code Playgroud)
这只是 vDSO 调用的一个薄包装,vDSO 是 Linux 内核本身的一部分。如果您好奇,请查找clock_gettime那里的定义。clock_gettime在 vDSO 中很不寻常,只有少数系统调用以这种方式实现。
这是 的 x86 实现CLOCK_REALTIME,可在arch/x86/entry/vdso/vclock_gettime.c以下位置找到:
/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
notrace static int __always_inline do_realtime(struct timespec *ts)
{
unsigned long seq;
u64 ns;
int mode;
do {
seq = gtod_read_begin(gtod);
mode = gtod->vclock_mode;
ts->tv_sec = gtod->wall_time_sec;
ns = gtod->wall_time_snsec;
ns += vgetsns(&mode);
ns >>= gtod->shift;
} while (unlikely(gtod_read_retry(gtod, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;
return mode;
}
Run Code Online (Sandbox Code Playgroud)
基本上,您的进程中有一些内存由内核更新,而 CPU 中有一些寄存器可以跟踪时间的流逝(或您的管理程序提供的某些内容)。进程中的内存用于将这些 CPU 寄存器的值转换为挂钟时间。您必须在循环中阅读这些内容,因为在您阅读它们时它们可能会发生变化……循环逻辑会检测读取错误时的情况,然后再试一次。
| 归档时间: |
|
| 查看次数: |
1271 次 |
| 最近记录: |