如果我编译了以下程序:
$ cat main.cpp && g++ main.cpp
#include <time.h>
int main() {
struct timespec ts;
return clock_gettime(CLOCK_MONOTONIC, &ts);
}然后在“标准”Kubuntu中在strace下运行它,我得到以下内容:
strace -tt --trace=clock_gettime ./a.out
17:58:40.395200 +++ exited with 0 +++如您所见,没有clock_gettime (完整的strace输出是这里)。
另一方面,如果我在qemu下自定义构建的linux内核中运行相同的应用程序,则得到以下输出:
strace -tt --trace=clock_gettime ./a.out
18:00:53.082115 clock_gettime(CLOCK_MONOTONIC, {tv_sec=101481, tv_nsec=107976517}) = 0
18:00:53.082331 +++ exited with 0 +++更让人期待的是--有clock_gettime。
所以,我的问题是
strace,为什么要忽略/忽略clock_gettime?strace的行为因环境/内核的不同而不同?发布于 2021-07-26 20:08:56
对第一个问题的回答
来自vdso人
strace(1)、seccomp(2)和vDSO
当使用strace(1)跟踪系统调用时,由vDSO 导出的符号(系统调用)将不会出现在跟踪输出中。同样,那些系统调用对于seccomp(2)过滤器也是不可见的。
回答回答第二个问题:
在vDSO中,clock_gettimeofday和相关函数依赖于特定的时钟模式;参见__arch_get_hw_counter。
如果时钟模式是VCLOCK_TSC,则使用RDTSC读取时间而不使用syscall;如果是VCLOCK_PVCLOCK或VCLOCK_HVCLOCK,则从特定页面读取时间以从管理程序检索信息。不声明时钟模式,因此它以默认的VCLOCK_NONE结束,vDSO发出一个系统调用来检索时间。
事实上:
在默认内核中(来自Kubuntu):
$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm
$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc自定义构建内核:
$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
hpet关于各种时钟源的更多信息。特别是:
Red版本2的文档指出,TSC是首选的时钟源,因为它的开销要低得多,但它使用HPET作为后盾。在该环境中,1000万次事件计数的基准值发现,TSC花费了大约0.6秒,HPET花费了12秒多一点,ACPI电源管理计时器花费了大约24秒。
发布于 2021-07-26 20:09:36
这可能是因为clock_gettime()是优化系统的一部分。看看这个回答中描述的vdso机制。
考虑到clock_gettime(),在某些体系结构(例如ARM v7 32位上的Linux 32位)上,VDSO实现中只支持可用时钟标识符的子集。对于其他人来说,在实际的系统调用中有一个退步。下面是clock_gettime()在Linux内核中用于ARM v7的VDSO实现的源代码(源代码树中的文件arch/arm/vdso/vgettimeofday.c ):
notrace int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
{
struct vdso_data *vdata;
int ret = -1;
vdata = __get_datapage();
switch (clkid) {
case CLOCK_REALTIME_COARSE:
ret = do_realtime_coarse(ts, vdata);
break;
case CLOCK_MONOTONIC_COARSE:
ret = do_monotonic_coarse(ts, vdata);
break;
case CLOCK_REALTIME:
ret = do_realtime(ts, vdata);
break;
case CLOCK_MONOTONIC:
ret = do_monotonic(ts, vdata);
break;
default:
break;
}
if (ret)
ret = clock_gettime_fallback(clkid, ts);
return ret;
}上面的源代码显示了一个具有受支持的时钟标识符的switch/case,在默认情况下,有一个回退到实际的系统调用。
在这种体系结构上,监视一个使用CLOCK_MONOTONIC和CLOCK_BOOTTIME,strace使用clock_gettime()的systemd这样的软件,只显示带有后一个标识符的调用,因为它不是VDSO模式支持的情况的一部分。
请参阅此链接可供参考
https://stackoverflow.com/questions/68535146
复制相似问题