clock_gettime在内核中的实际工作原理探究
clock_gettime在内核中的实际工作原理探究
咱们先从这段用来测试clock_gettime调用延迟的代码聊起,很多开发者会用类似写法来衡量这个系统调用的实际开销:
uint64_t getTimeLatencyNs() { struct timespec ts1; struct timespec ts2; clock_gettime(CLOCK_MONOTONIC_RAW, &ts1); clock_gettime(CLOCK_MONOTONIC_RAW, &ts2); return ((ts2.tv_sec - ts1.tv_sec) * NSEC + ts2.tv_nsec - ts1.tv_nsec); }
接下来咱们拆解下,当你调用clock_gettime的时候,内核到底在干些什么:
- 首先,用户态的这个函数调用会触发系统调用陷入,从用户态切换到内核态——这是所有系统调用的必经步骤,也是开销的一部分来源。
- 内核拿到请求后,先判断你指定的时钟类型:比如代码里用的
CLOCK_MONOTONIC_RAW,是个不接收NTP时间校准的单调时钟,它只会跟着硬件时钟的节奏稳步增加,绝不会因为系统时间调整出现跳变或者回退。 - 然后内核会去读取对应时钟的当前值:如果是x86架构的机器,大多会用TSC(时间戳计数器)这个硬件寄存器——内核会提前校准好TSC的频率,读取后直接把计数器值转换成秒和纳秒的格式;如果是其他架构或者用了其他硬件时钟源,内核会通过对应的驱动去读取硬件寄存器,再完成格式转换。
- 最后,内核把组装好的
timespec结构体数据拷贝回用户态的内存地址,再从内核态切回用户态,整个调用流程就完成了。
你用这段代码测出的时间差,基本就是两次clock_gettime系统调用的总开销(包括两次态切换、内核处理、数据拷贝的时间),因为用户态里除了调用和计算几乎没别的逻辑,结果能很贴近真实的调用延迟。
内容来源于stack exchange
相关产品推荐
相关产品推荐

