如何在Linux应用层和内核层获取时间

时间:2024-04-05 12:33:30

【1】应用层

gettimeofday函数
头文件:
#include <sys/time.h>
int gettimeofday(struct timeval*tv, struct timezone *tz);

其参数tv是保存获取时间结果的结构体,参数tz用于保存时区结果:
struct timezone{
int tz_minuteswest;/格林威治时间往西方的时差/
int tz_dsttime;/DST 时间的修正方式/
}

timezone 参数若不使用则传入NULL即可。

结构体定义:
而结构体timeval的定义为:
struct timeval{
long int tv_sec; // 秒数
long int tv_usec; // 微秒数
}

它获得的时间精确到微秒(1e-6 s)量级。在一段代码前后分别使用gettimeofday可以计算代码执行时间:

NAME
       gettimeofday, settimeofday - get / set time

SYNOPSIS
       #include <sys/time.h>

       int gettimeofday(struct timeval *tv, struct timezone *tz);

       int settimeofday(const struct timeval *tv, const struct timezone *tz);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       settimeofday(): _BSD_SOURCE

DESCRIPTION
       The  functions  gettimeofday()  and  settimeofday() can get and set the
       time as well as a timezone.  The tv argument is a  struct  timeval  (as
       specified in <sys/time.h>):

           struct timeval {
               time_t      tv_sec;     /* seconds */
               suseconds_t tv_usec;    /* microseconds */
           };

       and  gives  the number of seconds and microseconds since the Epoch (see
       time(2)).  The tz argument is a struct timezone:

           struct timezone {
               int tz_minuteswest;     /* minutes west of Greenwich */
               int tz_dsttime;         /* type of DST correction */
           };

代码实例:

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#define N 10

/*制作计时器*/
void mdelay(int ms_count)
{
            struct timeval tpStart, tpEnd;

            float timeUse;

            gettimeofday(&tpStart, NULL);

        do {
            gettimeofday(&tpEnd, NULL);
            timeUse = 1000 * (tpEnd.tv_sec - tpStart.tv_sec) + 0.001 * (tpEnd.tv_usec - tpStart.tv_usec);
        } while(timeUse < ms_count);
}

int main(int argc,char * argv[]){

        struct timeval t_start,t_end;

        long cost_time = 0;

        int i,time=N*10000;
        //get start time 
        gettimeofday(&t_start, NULL);
        long start = ((long)t_start.tv_sec)*1000+(long)t_start.tv_usec/1000;
        printf("Start time: %ld ms\n", start);//将时间转化为毫秒

/*延时10s*/
        for(i=0;i<10000;i++)
        {
                mdelay(1);
        }

        //get end time 
        gettimeofday(&t_end, NULL);
        long end = ((long)t_end.tv_sec)*1000+(long)t_end.tv_usec/1000;
        printf("End time: %ld ms\n", end);

        //calculate time slot 
        cost_time = end - start;
        printf("Cost time: %ld ms\n", cost_time);

        return 0;

}

实验结果:
如何在Linux应用层和内核层获取时间

存在一定误差!

【2】内核层

do_gettimeofday()函数

do_gettimeofday(struct timeval tv)
struct timeval {
__kernel_time_t tv_sec; /
seconds /
__kernel_suseconds_t tv_usec; /
microseconds */
};

#include <linux/init.h>         /* printk() */
#include <linux/module.h>       /* __init __exit */
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/timex.h>
#include <linux/rtc.h>

static int  __init  hello_init(void)      /*模块加载函数,通过insmod命令加载模块时,被自动执行*/
{
        printk("hello world!\n");
        int i;
        struct timeval start,end;
        long cost_time = 0;
        do_gettimeofday(&start);//获取开始时间
        long start_time = ((long)start.tv_sec)*1000+(long)start.tv_usec/1000;
     
        printk("Start time: %ld ms\n", start_time);//打印开始时间
/*延时10s*/
        for(i=0;i<10;i++)
        {
                udelay(1000000);
        }
        do_gettimeofday(&end);//获取结束时间

        long end_time = ((long)end.tv_sec)*1000+(long)end.tv_usec/1000;
        printk("End time: %ld ms\n", end_time);
        //printk("%ld\n",end.tv_usec);

         cost_time = end_time - start_time;//差值
         printk("Cost time: %ld ms\n", cost_time);

          return 0;
}

static void  __exit  hello_exit(void)    /*模块卸载函数,当通过rmmod命令卸载时,会被自动执行*/
{
          printk(KERN_INFO " Hello World exit\n ");

}


module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("shawn.wang");           /*模块作者,可选*/
MODULE_LICENSE("Dual BSD/GPL");     /*模块许可证明,描述内核模块的许可权限,必须*/
MODULE_DESCRIPTION("A simple Hello World Module"); /*模块说明,可选*/