首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么strace会根据环境/内核而忽略一些系统(随机)?

为什么strace会根据环境/内核而忽略一些系统(随机)?
EN

Stack Overflow用户
提问于 2021-07-26 18:58:05
回答 2查看 231关注 0票数 3

如果我编译了以下程序:

代码语言:javascript
复制
$ cat main.cpp && g++ main.cpp
#include <time.h>
int main() {
    struct timespec ts;
    return clock_gettime(CLOCK_MONOTONIC, &ts);
}

然后在“标准”Kubuntu中在strace下运行它,我得到以下内容:

代码语言:javascript
复制
strace -tt --trace=clock_gettime ./a.out
17:58:40.395200 +++ exited with 0 +++

如您所见,没有clock_gettime (完整的strace输出是这里)。

另一方面,如果我在qemu下自定义构建的linux内核中运行相同的应用程序,则得到以下输出:

代码语言:javascript
复制
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

所以,我的问题是

  • 如果我在Kubuntu中运行strace,为什么要忽略/忽略clock_gettime
  • 为什么strace的行为因环境/内核的不同而不同?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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):

代码语言:javascript
复制
$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm
$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc

自定义构建内核:

代码语言:javascript
复制
$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
hpet

关于各种时钟源的更多信息。特别是:

Red版本2的文档指出,TSC是首选的时钟源,因为它的开销要低得多,但它使用HPET作为后盾。在该环境中,1000万次事件计数的基准值发现,TSC花费了大约0.6秒,HPET花费了12秒多一点,ACPI电源管理计时器花费了大约24秒。

票数 1
EN

Stack Overflow用户

发布于 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 ):

代码语言:javascript
复制
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_MONOTONICCLOCK_BOOTTIMEstrace使用clock_gettime()的systemd这样的软件,只显示带有后一个标识符的调用,因为它不是VDSO模式支持的情况的一部分。

请参阅此链接可供参考

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68535146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档