разница между time () и gettimeofday () и почему один вызывает ошибку seg

Я пытаюсь измерить время системного вызова, и я попытался с помощью time(0) и gettimeofday() в этой программе, но всякий раз, когда я использую gettimeofday() это ошибки seg. Полагаю, я могу просто использовать time(0) но я хотел бы знать, почему это происходит. И я знаю, что вы, ребята, можете просто посмотреть на это и увидеть проблему. Пожалуйста, не кричи на меня!

Я хочу получить время, но не сохранить его нигде.

Я пробовал каждую комбинацию кода, о которой я могу думать, но я вставил самый простой версия здесь. Я новичок в C и Linux. Я смотрю на него .stackdump файл, но это довольно бессмысленно для меня.

GetRDTSC находится в util.h И это делает rdtsc(), как и следовало ожидать. Теперь он установлен на 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("%in", (int)(cycles[i]));
    }  
}

1 ответов


короткая версия

gettimeofday() требуется указатель на struct timeval для заполнения данных времени.

так, например, вы бы сделали что-то вроде этого:

#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;
}

длинная версия

на реальные проблема в том, что gcc автоматически включает vdso в вашей системе, которая содержит символ для syscall gettimeofday. Рассмотрим эту программу (весь файл):

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

по умолчанию gcc скомпилирует это без предупреждения. Если вы проверите символы, с которыми он связан, вы увидите:

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)

вы просто используете функцию, которая имеет определенный символ, но без прототипа невозможно сказать, сколько аргументов командной строки она должна иметь.

если вы скомпилируете его с -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]

конечно, это будет segfault, когда вы попытаетесь запустить его. Интересно, что это будет segfault в пространстве ядра (это включено 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 ()

Теперь рассмотрим эту программу (опять же, нет заголовочных файлов):

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

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

это будет компилироваться и работать просто отлично-нет segfault. Вы предоставили ему местоположение памяти, которое он ожидает, хотя по-прежнему нет gettimeofday прототип предусмотрено.

дополнительная информация:

может ли кто-нибудь понять, как работает gettimeofday?

есть ли более быстрый эквивалент gettimeofday?

спецификация POSIX gettimeofday