Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.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
C中的time()函数是如何工作的?_C_Time - Fatal编程技术网

C中的time()函数是如何工作的?

C中的time()函数是如何工作的?,c,time,C,Time,有谁知道time()函数是如何工作的 我纯粹出于好奇在网上寻找实现,但只能找到的NetBSD实现 是否有任何内容描述了计算时间的过程(非系统特定或系统特定) 注意:我不是在寻找如何使用time()的答案,而是在我调用它时它在幕后是如何工作的 C规范没有说明库函数是如何工作的。它只说明可观察到的行为。内部工作既依赖于编译器,也依赖于平台 简介 #include <time.h> time_t time(time_t *timer); C规范没有说明库函数是如何工作的。

有谁知道
time()
函数是如何工作的

我纯粹出于好奇在网上寻找实现,但只能找到的NetBSD实现

是否有任何内容描述了计算时间的过程(非系统特定或系统特定)

注意:我不是在寻找如何使用
time()
的答案,而是在我调用它时它在幕后是如何工作的


C规范没有说明库函数是如何工作的。它只说明可观察到的行为。内部工作既依赖于编译器,也依赖于平台

简介

    #include <time.h>
    time_t time(time_t *timer);

C规范没有说明库函数是如何工作的。它只说明可观察到的行为。内部工作既依赖于编译器,也依赖于平台

简介

    #include <time.h>
    time_t time(time_t *timer);

在操作系统内核或CPU相关硬件的深处,有一个时钟振荡器以某个频率f运行。出于示例的目的,让我们假设它以1kHz或每秒1000个周期运行。振荡器的每个周期触发一个CPU中断

还有一个低级计数器
c
。每次触发时钟中断时,操作系统都会使计数器递增。目前,我们可以想象它会增加1,尽管在实践中通常不是这样

当计数器的值递增时,操作系统也会检查计数器的值。当
c
等于1000时,这意味着正好一秒钟过去了。此时,操作系统会做两件事:

  • 它增加另一个计数器变量,这个变量以秒为单位跟踪一天中的实际时间。我们将把这个计数器称为
    t
  • 它将
    c
    重置为0
  • 最后,当调用
    time()
    时,内核只返回
    t
    的当前值。这很简单,真的

    嗯,事实上,它比那要复杂一些。我忽略了计数器
    t
    的值最初是如何设置的,操作系统是如何确保振荡器以正确的频率运行的,以及其他一些细节

    当操作系统启动时,如果它在PC、工作站、大型机或其他“大型”计算机上,它通常有一个电池供电的实时时钟,可以用来设置
    t
    的初始值。(另一方面,如果我们谈论的CPU是嵌入式微控制器,那么它可能没有任何类型的时钟,所有这些都是没有意义的,
    time()
    根本没有实现。)

    另外,当您(以root用户身份)调用
    settimeofday
    时,您基本上只是提供了一个值以插入内核的
    t
    计数器

    当然,在大多数系统上,NTP都忙于保持系统的时间最新

    NTP可以通过两种方式做到这一点:

  • 如果它注意到
    t
    太远了,它可以将其设置为一个新值,或多或少就像
    settimeofday()
    所做的那样
  • 如果它注意到
    t
    只差一点点,或者如果它注意到基础振荡器的计数频率不正确,它可以尝试调整该频率
  • 调整频率听起来很简单,但细节可能会变得相当复杂。您可以想象,基础振荡器的频率f被稍微调整了一下。或者,您可以想象,当时间中断触发时,添加到
    c
    的增量会稍微调整

    特别是,通常情况下,内核不会在每个计时器中断时向
    c
    添加1,当
    c
    达到1000时,这表示一秒钟过去了。更可能的是,内核会在每个计时器中断时向
    c
    添加一个类似1000000的数字,这意味着它会等到
    c
    达到100000000之后,才决定一秒钟过去了。通过这种方式,内核可以对时钟频率进行更细粒度的调整:如果事情运行得有点慢,它可以改变主意,在每个计时器中断时向
    c
    添加1000001,这将使事情运行得稍微快一点。(正如你很容易看到的,大约是百万分之一。)

    我还忽略了一件事,
    time()
    不是询问系统时间的唯一方法。您还可以进行调用,如
    gettimeofday()
    ,它为您提供以秒+微秒(
    struct timeval
    )表示的亚秒时间戳,或
    clock\u gettime()
    ,它为您提供以秒+纳秒(
    struct timespec
    )表示的亚秒时间戳。这些措施是如何实施的?好的,内核不仅可以读取
    t
    的值,还可以查看
    c
    以查看它到下一秒有多远。特别是,如果
    c
    的计数高达100000000,那么内核可以通过将
    c
    乘以1000得到微秒,也可以通过直接返回
    c
    得到纳秒


    两个脚注:

    (1) 如果我们已经调整了频率,并且我们在每个低电平定时器节拍上向
    c
    添加1000001,
    c
    通常不会精确地达到100000000,因此在决定是否增加
    t
    时,测试必须涉及大于或等于的条件,我们必须从
    c
    中减去100000000,而不仅仅是清除它。换句话说,代码看起来像

    if(c >= 1000000000) {
        t++;
        c -= 1000000000;
    }
    
    (2) 由于
    time()
    gettimeofday()
    是两种最简单的系统调用,并且由于调用它们的程序(根据定义)可能会由于系统调用开销而对任何延迟特别敏感,因此这些调用最有可能基于