clockid_t与clock_gettime 函数

clockid_t

kernel的time基本类型:
1) system time
A monotonically increasing value that represents the amount of time the system has been running. 单调增长的系统运行时间, 可以通过time source, xtime及wall_to_monotonic计算出来.
2) wall time
A value representing the the human time of day, as seen on a wrist-watch. Realtime时间: xtime.
3) time source
A representation of a free running counter running at a known frequency, usually in hardware, e.g GPT. 可以通过clocksource->read()得到counter值
4) tick
A periodic interrupt generated by a hardware-timer, typically with a fixed interval defined by HZ: jiffies

这些time之间互相关联, 互相可以转换.
system_time = xtime + cyc2ns(clock->read() - clock->cycle_last) + wall_to_monotonic;
real_time = xtime + cyc2ns(clock->read() - clock->cycle_last)
也就是说real time是从1970年开始到现在的nanosecond, 而system time是系统启动到现在的nanosecond.
这两个是最重要的时间, 由此hrtimer可以基于这两个time来设置过期时间. 所以引入两个clock base:


CLOCK_REALTIME: base在实际的wall time
CLOCK_MONOTONIC: base在系统运行system time

CLOCK_REALTIME 调用ktime_get_real()来获得真实时间, 该函数用上面提到的等式计算出realtime.
CLOCK_MONOTONIC 调用ktime_get(), 用system_time的等式获得monotonic time.

Clock API

clock_gettime(clockid_t, struct timespec *)
获取对应clock的时间
clock_settime(clockid_t, const struct timespec *)
设置对应clock时间
clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *)
进程nano sleep
clock_getres(clockid_t, struct timespec *)
获取时间精度, 一般是nanosec

clockid_t 定义了四种clock:

CLOCK_REALTIME
System-wide realtime clock. Setting this clock requires appropriate privileges.
CLOCK_MONOTONIC
Clock that cannot be set and represents monotonic time since some unspecified starting point.
CLOCK_PROCESS_CPUTIME_ID
High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
Thread-specific CPU-time clock.


前两者前面提到了, 后两个是和进程/线程统计时间有关系, 应用层可以利用这四种clock, 提高灵活性及精度.

Timer API

Timer 可以建立进程定时器,单次或者周期性定时。

int timer_create(clockid_t clockid, struct sigevent *restrict evp, timer_t *restrict timerid);
创建定时器。
clockid 指定在哪个clock base下创建定时器。
evp (sigevent) 可以指定定时器到期后内核发送哪个信号给进程,以及信号所带参数;默认为SIGALRM。
timerid 返回所建timer的id号。
在signal 处理函数里,可以通过siginfo_t.si_timerid 获得当前的信号是由哪个timer过期触发的。试验了一下,最多可创建的timer数目和ulimit里的pending signals的有关系,不能超过pending signals的数量。

int timer_gettime(timer_t timerid, struct itimerspec *value);
获得timer的下次过期的时间。

int timer_settime(timer_t timerid, int flags, const struct itimerspec *restrict value, struct itimerspec *restrict ovalue);
设置定时器的过期时间及间隔周期。

int timer_delete(timer_t timerid);
删除定时器。

这些系统调用都会建立一个posix_timer的hrtimer,在过期的时候发送信号给进程。//注释1

clock_gettime 函数

#include<time.h>

int clock_gettime(clockid_t   clk_id,   struct timespec *tp);

clk_id 检索和设置的clk_id指定的时钟时间

CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,
                                   中间时刻如果系统时间被用户改成其他,则对应的时间相应改变
CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
CLOCK_PROCESS_CPUTIME_ID:本进程到当前代码系统CPU花费的时间
CLOCK_THREAD_CPUTIME_ID:本线程到当前代码系统CPU花费的时间
例子:

#include<stdio.h>
#include<time.h>
int main(int argc,char *argv[])
{        
    struct timespec time1 = {0, 0};   
      
    clock_gettime(CLOCK_REALTIME, &time1);        
    printf("CLOCK_REALTIME: %d, %d\n", time1.tv_sec, time1.tv_nsec);  
       
    clock_gettime(CLOCK_MONOTONIC, &time1);        
    printf("CLOCK_MONOTONIC: %d, %d\n", time1.tv_sec, time1.tv_nsec);    
     
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);        
    printf("CLOCK_PROCESS_CPUTIME_ID: %d, %d\n", time1.tv_sec, time1.tv_nsec);   
    
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time1);        
    printf("CLOCK_THREAD_CPUTIME_ID: %d, %d\n", time1.tv_sec, time1.tv_nsec);   
     
    printf("\n%d\n", time(NULL));
     
    sleep(5);
 
    return 0;
}

注释1:http://blog.chinaunix.net/uid-20321537-id-1966879.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
`clock_gettime` 函数函数体实现是由操作系统提供的,具体实现可能因操作系统而异。以下是一种可能的实现方式: ```C #include <time.h> #include <errno.h> #include <sys/time.h> #include <sys/resource.h> int clock_gettime(clockid_t clk_id, struct timespec *tp) { int ret = 0; struct timeval tv; struct timezone tz; if (clk_id != CLOCK_REALTIME && clk_id != CLOCK_MONOTONIC && clk_id != CLOCK_PROCESS_CPUTIME_ID && clk_id != CLOCK_THREAD_CPUTIME_ID) { errno = EINVAL; return -1; } if (tp == NULL) { errno = EFAULT; return -1; } if (clk_id == CLOCK_REALTIME) { ret = gettimeofday(&tv, &tz); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; } else if (clk_id == CLOCK_MONOTONIC) { ret = clock_gettime(CLOCK_MONOTONIC_RAW, tp); } else if (clk_id == CLOCK_PROCESS_CPUTIME_ID) { ret = getrusage(RUSAGE_SELF, &ru); tp->tv_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; tp->tv_nsec = ru.ru_utime.tv_usec * 1000 + ru.ru_stime.tv_usec * 1000; } else if (clk_id == CLOCK_THREAD_CPUTIME_ID) { ret = getrusage(RUSAGE_THREAD, &ru); tp->tv_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; tp->tv_nsec = ru.ru_utime.tv_usec * 1000 + ru.ru_stime.tv_usec * 1000; } if (ret == -1) { errno = EINVAL; return -1; } return 0; } ``` 这个实现中,函数首先检查 `clk_id` 是否是支持的时钟类型,以及 `tp` 是否为 `NULL`。然后,根据不同的时钟类型调用不同的系统函数获取时间值,并将结果存储到 `timespec` 结构体中。最后,返回 `0` 表示成功,或者返回 `-1` 表示失败并设置 `errno` 错误码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值