Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在哪里可以找到timespec\u get的源代码?_C_Linux_Glibc_C11_Timespec - Fatal编程技术网

在哪里可以找到timespec\u get的源代码?

在哪里可以找到timespec\u get的源代码?,c,linux,glibc,c11,timespec,C,Linux,Glibc,C11,Timespec,C11标准提供了该功能。如果我在cppreference或我的计算机上运行示例代码,它可以工作: #include <stdio.h> #include <time.h> int main(void) { struct timespec ts; timespec_get(&ts, TIME_UTC); char buff[100]; strftime(buff, sizeof buff, "%D %T", gmtime(&

C11
标准提供了该功能。如果我在cppreference或我的计算机上运行示例代码,它可以工作:

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

int main(void)
{
    struct timespec ts;
    timespec_get(&ts, TIME_UTC);
    char buff[100];
    strftime(buff, sizeof buff, "%D %T", gmtime(&ts.tv_sec));
    printf("Current time: %s.%09ld UTC\n", buff, ts.tv_nsec);
}
#包括
#包括
内部主(空)
{
结构timespects;
timespec_-get(&ts,TIME_-UTC);
字符buff[100];
strftime(buff,sizeof buff,“%D%T”,gmtime(&ts.tv_秒));
printf(“当前时间:%s.%09ld UTC\n”,buff,ts.tv\u nsec);
}
但是,如果我查看glibc的源代码,代码如下所示:

#include <time.h>


/* Set TS to calendar time based in time base BASE.  */
int
timespec_get (struct timespec *ts, int base)
{
  switch (base)
    {
    case TIME_UTC:
      /* Not supported.  */
      return 0;

    default:
      return 0;
    }

  return base;
}
stub_warning (timespec_get)
#包括
/*将TS设置为基于时基的日历时间*/
int
timespec_get(结构timespec*ts,int base)
{
开关(底座)
{
案例时间(UTC):
/*不支持*/
返回0;
违约:
返回0;
}
返回基地;
}
存根警告(timespec\u-get)
哪个。。。不应该工作


这就引出了一个问题:实际调用的
timespec\u get
的源代码在哪里?

您链接到的
timespec\u get
定义是存根(请参阅
stub\u警告
)。实际实现将在您平台的
sysdeps
下进行。例如,
sysv
的版本如下:


timespec_-get
函数的实现取决于库运行的系统,因此它在
time/timespec_-get.c
中显示为存根(如果没有可用的实现),在其他地方显示为各种依赖于系统的实现

您可以在sysdeps/unix/sysv/Linux/timespec\u get.c中看到Linux实现

/* Set TS to calendar time based in time base BASE.  */
int
timespec_get (struct timespec *ts, int base)
{
  switch (base)
    {
      int res;
      INTERNAL_SYSCALL_DECL (err);
    case TIME_UTC:
      res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, ts);
      if (INTERNAL_SYSCALL_ERROR_P (res, err))
        return 0;
      break;

    default:
      return 0;
    }

  return base;
}
这只是一个围绕vDSO调用的薄包装,vDSO本身就是Linux内核的一部分。如果您感到好奇,请在此处查找
clock\u gettime
的定义。不寻常的是,
clock\u gettime
在vDSO中,只有少数系统调用是以这种方式实现的

以下是用于
CLOCK\u REALTIME
的x86实现,可在
arch/x86/entry/vdso/vclock\u gettime.c
中找到:

/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
notrace static int __always_inline do_realtime(struct timespec *ts)
{
        unsigned long seq;
        u64 ns;
        int mode;

        do {
                seq = gtod_read_begin(gtod);
                mode = gtod->vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ns = gtod->wall_time_snsec;
                ns += vgetsns(&mode);
                ns >>= gtod->shift;
        } while (unlikely(gtod_read_retry(gtod, seq)));

        ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
        ts->tv_nsec = ns;

        return mode;
}
基本上,进程中有一些内存由内核更新,CPU中有一些寄存器跟踪时间的流逝(或者由系统管理程序提供)。进程中的内存用于将这些CPU寄存器的值转换为挂钟时间。你必须在一个循环中阅读这些内容,因为当你阅读它们时,它们可能会改变。。。当读取错误时,循环逻辑会检测情况,然后重试

/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
notrace static int __always_inline do_realtime(struct timespec *ts)
{
        unsigned long seq;
        u64 ns;
        int mode;

        do {
                seq = gtod_read_begin(gtod);
                mode = gtod->vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ns = gtod->wall_time_snsec;
                ns += vgetsns(&mode);
                ns >>= gtod->shift;
        } while (unlikely(gtod_read_retry(gtod, seq)));

        ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
        ts->tv_nsec = ns;

        return mode;
}