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
重置为0time()
时,内核只返回t
的当前值。这很简单,真的
嗯,事实上,它比那要复杂一些。我忽略了计数器t
的值最初是如何设置的,操作系统是如何确保振荡器以正确的频率运行的,以及其他一些细节
当操作系统启动时,如果它在PC、工作站、大型机或其他“大型”计算机上,它通常有一个电池供电的实时时钟,可以用来设置t
的初始值。(另一方面,如果我们谈论的CPU是嵌入式微控制器,那么它可能没有任何类型的时钟,所有这些都是没有意义的,time()
根本没有实现。)
另外,当您(以root用户身份)调用settimeofday
时,您基本上只是提供了一个值以插入内核的t
计数器
当然,在大多数系统上,NTP都忙于保持系统的时间最新
NTP可以通过两种方式做到这一点:
t
太远了,它可以将其设置为一个新值,或多或少就像settimeofday()
所做的那样t
只差一点点,或者如果它注意到基础振荡器的计数频率不正确,它可以尝试调整该频率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()
是两种最简单的系统调用,并且由于调用它们的程序(根据定义)可能会由于系统调用开销而对任何延迟特别敏感,因此这些调用最有可能基于