简体   繁体   English

time()和gettimeofday()之间的差异以及为什么会导致seg错误

[英]difference between time() and gettimeofday() and why does one cause seg fault

I'm trying to measure the amount of time for a system call, and I tried using time(0) and gettimeofday() in this program, but whenever I use gettimeofday() it seg faults. 我正在尝试测量系统调用的时间,我尝试在这个程序中使用time(0)gettimeofday() ,但每当我使用gettimeofday()它就会出现错误。 I suppose I can just use time(0) but I'd like to know why this is happening. 我想我可以使用time(0)但我想知道为什么会这样。 And I know you guys can just look at it and see the problem. 我知道你们可以看看它并看到问题所在。 Please don't yell at me! 请不要对我大喊大叫!

I want to get the time but not save it anywhere. 我想得到时间,但不能保存在任何地方。

I've tried every combination of code I can think of but I pasted the simplest version here. 我已经尝试了我能想到的每种代码组合,但是我在这里粘贴了最简单的版本。 I'm new to C and Linux. 我是C和Linux的新手。 I look at the .stackdump file but it's pretty meaningless to me. 我看一下.stackdump文件,但这对我来说毫无意义。

GetRDTSC is in util.h and it does rdtsc() , as one might expect. GetRDTSC位于util.h中,它可以像人们所期望的那样执行rdtsc() Now it's set to 10 iterations but later the loop will run 1000 times, without printf . 现在它设置为10次迭代但后来循环将运行1000次,没有printf

#include <stdio.h>
#include <time.h>
#include "util.h"

int main() {

    int i;
    uint64_t cycles[10];

    for (i = 0; i < 10; ++i) {

         // get initial cycles
         uint64_t init = GetRDTSC();

         gettimeofday(); // <== time(0) will work here without a seg fault.

         // get cycles after
         uint64_t after = GetRDTSC();   

         // save cycles for each operation in an array
         cycles[i] = after - init;

         printf("%i\n", (int)(cycles[i]));
    }  
}

The short version 简短的版本

gettimeofday() requires a pointer to a struct timeval to fill with time data. gettimeofday()需要一个指向struct timeval的指针来填充时间数据。

So, for example, you'd do something like this: 所以,例如,你会做这样的事情:

#include <sys/time.h>
#include <stdio.h>
int main() {  
    struct timeval tv;
    gettimeofday(&tv, NULL); // timezone should be NULL
    printf("%d seconds\n", tv.tv_secs);
    return 0;
}

The long version 长版

The real problem is that gcc is automatically including vdso on your system, which contains a symbol for the syscall gettimeofday . 真正的问题是gcc会在你的系统上自动包含vdso ,其中包含一个syscall gettimeofday的符号。 Consider this program (entire file): 考虑这个程序(整个文件):

int main() {
  gettimeofday();
  return 0;
}

By default, gcc will compile this without warning . 默认情况下,gcc会在没有警告的情况下编译它。 If you check the symbols it's linked against, you'll see: 如果你检查它链接的符号,你会看到:

ternus@event-horizon ~> gcc -o foo foo.c
ternus@event-horizon ~> ldd foo
        linux-vdso.so.1 =>  (0x00007ffff33fe000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f56a5255000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f56a562b000)

You just happen to be using a function that has a defined symbol, but without the prototype, there's no way to tell how many command-line arguments it's supposed to have. 您恰好正在使用具有已定义符号的函数,但如果没有原型,则无法确定它应该具有多少命令行参数。

If you compile it with -Wall , you'll see: 如果你用-Wall编译它,你会看到:

ternus@event-horizon ~> gcc -Wall -o foo foo.c
foo.c: In function ‘main’:
foo.c:2:3: warning: implicit declaration of function ‘gettimeofday’ [-Wimplicit-function-declaration]

Of course, it'll segfault when you try to run it. 当然,当你尝试运行它时会出现段错误。 Interestingly, it'll segfault in kernel space (this is on MacOS): 有趣的是,它在内核空间中会出现段错误(这是在MacOS上):

cternus@astarael ~/foo> gcc -o foo -g foo.c
cternus@astarael ~/foo> gdb foo
GNU gdb 6.3.50-20050815 (Apple version gdb-1822) (Sun Aug  5 03:00:42 UTC 2012)
[etc]

(gdb) run
Starting program: /Users/cternus/foo/foo
Reading symbols for shared libraries +.............................. done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000001
0x00007fff87eeab73 in __commpage_gettimeofday ()

Now consider this program (again, no header files): 现在考虑这个程序(再次,没有头文件):

typedef struct {
  long tv_sec;
  long tv_usec;
} timeval;

int main() {
  timeval tv;
  gettimeofday(&tv, 0);
  return 0;
}

This will compile and run just fine -- no segfault. 这将编译并运行得很好 - 没有段错误。 You've provided it with the memory location it expects, even though there's still no gettimeofday prototype provided. 你已经为它提供了它所期望的内存位置,即使仍然没有提供gettimeofday原型。

More information: 更多信息:

Can anyone understand how gettimeofday works? 任何人都能理解gettimeofday的工作原理吗?

Is there a faster equivalent of gettimeofday? 是否有更快的gettimeofday相当于?

The POSIX gettimeofday specification POSIX gettimeofday规范

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM