我在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蚀刻中工作正常。
有人可以向我解释为什么会出现这种情况以及如何解决这个问题?
非常感谢。
答案 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
。
一些更简单的测试想法:
-m32
添加到gcc命令,在Ubuntu主机系统中编译并运行32位测试程序。内核的32位兼容模式可能导致错误。如果是这种情况,那么无论链接到哪个libc,32位版本都将失败。然后是硬盘的时候了。查看反汇编代码,也许单步执行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;
}
我通过下载蚀刻libc来复制这个。这肯定会导致glibc愚蠢。它不是一个简单的用于clock_gettime的系统调用包装器,它有一大堆预处理器意大利面,最终导致“你不能使用我们没有预先批准的clockid”。你不会让它与旧的glibc一起工作。这让我们想到了一个我不想问的问题:你为什么要尝试使用过时的Debian版本?