clock_gettime在使用CLOCK_PROCESS_CPUTIME_ID的chrooted Debian etch中失败

时间:2012-08-21 23:17:49

标签: c++ ubuntu debian clock chroot

我在Ubuntu 12.04(64位)下设置了一个chrooted Debian Etch(32位),看起来clock_gettime()与CLOCK_MONOTONIC一起使用,但是同时失败了CLOCK_PROCESS_CPUTIME_ID和CLOCK_THREAD_CPUTIME_ID。 errno设置为EINVAL,根据手册页表示“此系统不支持指定的clk_id。”

所有三个时钟在被剔除的Debian之外以及64位chrooted Debian蚀刻中工作正常。

有人可以向我解释为什么会出现这种情况以及如何解决这个问题?

非常感谢。

1 个答案:

答案 0 :(得分:1)

我还不知道原因,但我的想法不适合评论框。

首先,您可以通过将其编译为C而不是C ++而不将其链接到libpthread来使测试程序更简单。 -lrt应该足以获得clock_gettime。此外,使用-static进行编译可以使跟踪更容易,因为动态链接器启动内容不会出现。

静态链接甚至可能会改变clock_gettime的行为。值得一试的是找出它是否能够解决这个问题。

我希望看到的另一件事是这个vdso旁路测试程序的输出:

#define _GNU_SOURCE
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/syscall.h>

int main(void)
{
    struct timespec ts;
    if(syscall(SYS_clock_gettime, CLOCK_PROCESS_CPUTIME_ID, &ts)) {
        perror("clock_gettime");
        return 1;
    }
    printf("CLOCK_PROCESS_CPUTIME_ID: %lu.%09ld\n",
           (unsigned long)ts.tv_sec, ts.tv_nsec);
    return 0;
}

有和没有-static,如果失败,请添加strace

更新(实际上,跳过这个。转到第二次更新)

一些更简单的测试想法:

  1. 通过将-m32添加到gcc命令,在Ubuntu主机系统中编译并运行32位测试程序。内核的32位兼容模式可能导致错误。如果是这种情况,那么无论链接到哪个libc,32位版本都将失败。
  2. 获取您在Debian下编译的非静态测试程序,将它们复制到Ubuntu主机系统并尝试在那里运行它们。行为的改变将指向libc作为原因。
  3. 然后是硬盘的时候了。查看反汇编代码,也许单步执行gdb。我希望得到你正在运行的代码的副本,而不是让你自己这样做。上传一个静态编译的失败测试程序,我可以得到它。另外,内核提供的32位vdso副本可能很有趣。要提取vdso,请运行以下程序(在32位chroot中编译),该程序将创建一个名为vdso.dump的文件,并上传该文件。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int getvseg(const char *which, const char *outfn)
    {
      FILE *maps, *outfile;
      char buf[1024];
      void *start, *end;
      size_t sz;
      void *copy;
      int ret;
      char search[strlen(which)+4];
    
      maps = fopen("/proc/self/maps", "r");
      if(!maps) {
        perror("/proc/self/maps");
        return 1;
      }
      outfile = fopen(outfn, "w");
      if(!outfile) {
        perror(outfn);
        fclose(maps);
        return 1;
      }
    
      sprintf(search, "[%s]\n", which);
      while(fgets(buf, sizeof buf, maps)) {
        if(strlen(buf)<strlen(search) ||
           strcmp(buf+strlen(buf)-strlen(search),search))
          continue;
        if(sscanf(buf, "%p-%p", &start, &end)!=2) {
          fprintf(stderr, "weird line in /proc/self/maps: %s", buf);
          continue;
        }
        sz = (char *)end - (char *)start;
        /* copy because I got an EFAULT trying to write directly from vsyscall */
        copy = malloc(sz);
        if(!copy) {
          perror("malloc");
          goto fail;
        }
        memcpy(copy, start, sz);
        if(fwrite(copy, 1, sz, outfile)!=sz) {
          if(ferror(outfile))
            perror(outfn);
          else
            fprintf(stderr, "%s: short write", outfn);
          free(copy);
          goto fail;
        }
        free(copy);
        goto success;
      }
      fprintf(stderr, "%s not found\n", which);
    
    fail:
      ret = 1;
      goto out;
    success:
      ret = 0;
    out:
      fclose(maps);
      fclose(outfile);
      return ret;
    }
    
    int main(void)
    {
      int ret = 1;
      if(!getvseg("vdso", "vdso.dump")) {
        printf("vdso dumped to vdso.dump\n");
        ret = 0;
      }
      if(!getvseg("vsyscall", "vsyscall.dump")) {
        printf("vsyscall dumped to vsyscall.dump\n");
        ret = 0;
      }
      return ret;
    }
    

    更新2

    我通过下载蚀刻libc来复制这个。这肯定会导致glibc愚蠢。它不是一个简单的用于clock_gettime的系统调用包装器,它有一大堆预处理器意大利面,最终导致“你不能使用我们没有预先批准的clockid”。你不会让它与旧的glibc一起工作。这让我们想到了一个我不想问的问题:你为什么要尝试使用过时的Debian版本?