kernel获取毫秒、微妙时间

前言:

有时需要在kernel中测试一个函数或者语句的执行时间,就要获取精确的毫秒、微妙的值。下面记录一下两种获取时间的方法及测试结果:

Kernel: v4.4.159

Device: rk3328

Platform Version: Android 9.0

方式1:(推荐使用)

#include <linux/time.h> //需要包含的头文件
struct timeval tstart;  //结构体
do_gettimeofday(&tstart);//获取时间
//打印秒、微妙值
printk("%s, stime: %lds, utime: %ldus\n"\
        , __func__, tstart.tv_sec, tstart.tv_usec);

方式2:(经测试时间未变,不适用于此场景)

#include <linux/time.h>//需要包含的文件
struct timespec time0 = current_kernel_time();//获取时间
//打印秒、纳秒值
printk("%s, stime: %lds, ntime: %ldns\n",\
             __func__, time0.tv_sec, time0.tv_nsec);

测试方式1

void test1(void)
{
    struct timeval tstart, tend;
    printk("----------------------------------------------------\n");
    do_gettimeofday(&tstart);
    printk("%s, stime: %lds, utime: %ldus\n", __func__, tstart.tv_sec, tstart.tv_usec);
    printk("%s, before mtime: %ldms\n", __func__, 1000 * tstart.tv_sec + tstart.tv_usec / 1000);
    mdelay(1);//延时1ms
    do_gettimeofday(&tend);
    printk("%s, stime: %lds, utime: %ldus\n", __func__, tend.tv_sec, tend.tv_usec);
    printk("%s, after mtime: %ldms\n", __func__, 1000 * tend.tv_sec + tend.tv_usec / 1000);
    printk("%s, time taken: %ldms\n", __func__, 1000 * (tend.tv_sec - tstart.tv_sec) + (tend.tv_usec - tstart.tv_usec) / 1000);
}

1

void test2(void)
{
    struct timeval tstart, tend;
    printk("----------------------------------------------------\n");
    do_gettimeofday(&tstart);
    printk("%s, stime: %lds, utime: %ldus\n", __func__, tstart.tv_sec, tstart.tv_usec);
       printk("%s, before mtime: %ldus\n", __func__, 1000 * 1000 * tstart.tv_sec + tstart.tv_usec);
    udelay(1);//延时1us
    do_gettimeofday(&tend);
    printk("%s, stime: %lds, utime: %ldus\n", __func__, tend.tv_sec, tend.tv_usec);
    printk("%s, after mtime: %ldus\n", __func__, 1000 * 1000 * tend.tv_sec + tend.tv_usec);
    printk("%s, time taken: %ldus\n", __func__, 1000 * 1000 * (tend.tv_sec - tstart.tv_sec) + (tend.tv_usec - tstart.tv_usec));
}

1

测试方式2

void test3(void)
{
    struct timespec time0, time1;
    printk("----------------------------------------------------\n");
    time0 = current_kernel_time();
    printk("%s, before stime: %lds, ntime: %ldns\n", __func__, time0.tv_sec, time0.tv_nsec);
    mdelay(1);//延时1ms
    time1 = current_kernel_time();
    printk("%s, after stime: %lds, ntime: %ldns\n", __func__, time1.tv_sec, time1.tv_nsec);
    printk("%s, ntime taken: %ldns\n", __func__, time1.tv_nsec - time0.tv_nsec);
}

void test4(void)
{
    struct timespec time0, time1;
    printk("----------------------------------------------------\n");
    time0 = current_kernel_time();
    printk("%s, before stime: %lds, ntime: %ldns\n", __func__, time0.tv_sec, time0.tv_nsec);
    udelay(1);//延时1us
    time1 = current_kernel_time();
    printk("%s, after stime: %lds, ntime: %ldns\n", __func__, time1.tv_sec, time1.tv_nsec);
    printk("%s, ntime taken: %ldns\n", __func__, time1.tv_nsec - time0.tv_nsec);
}

void test5(void)
{
    struct timespec time0, time1;
    printk("----------------------------------------------------\n");
    time0 = current_kernel_time();
    printk("%s, before stime: %lds, ntime: %ldns\n", __func__, time0.tv_sec, time0.tv_nsec);
    ndelay(1);//延时1ns
    time1 = current_kernel_time();
    printk("%s, after stime: %lds, ntime: %ldns\n", __func__, time1.tv_sec, time1.tv_nsec);
    printk("%s, ntime taken: %ldns\n", __func__, time1.tv_nsec - time0.tv_nsec);
}    

1

结论: current_kernel_time用于计时,而不用于性能测量.
它返回的值不是基于实际的定时器,而是基于定时器中断更新的时间值.因此精度取决于定时器中断周期.

转载请注明出处:http://www.wolfnx.com/2019/02/06/KernelGetPreciseTime

作者 : wolfnx
邮箱 : wolfnx@outlook.com
邮箱2 : lostnx@gmail.com

Click Me