Summary of Linux time related knowledge: struct timeval, timespec, gettimeofday, time, localtime

Posted by schwa97 on Sun, 06 Feb 2022 19:22:32 +0100

preface

When we are developing on linux platform, we will basically encounter time-related operations. This paper analyzes and summarizes the commonly used time-related structures and interfaces.

Common types and structure definitions

timespec

prototype

struct timespec
{
  __time_t tv_sec;		/* Seconds. second */
  __syscall_slong_t tv_nsec;	/* Nanoseconds.  nanosecond*/
};

explain

The structure only includes seconds and nanoseconds, and has no other meaning, such as the number of seconds since 1970. Just a storage space. Is clock_ The output parameter of gettime.

clock_gettime

prototype

int clock_gettime (clockid_t __clock_id, struct timespec *__tp);

explain

According to clock_ ID (system clock) to get the current time.

Parameter description

clock_ Enumeration description of common values of ID

enum explain
CLOCK_REALTIMEThe current time of the system is calculated from January 1, 1970
CLOCK_MONOTONICElapsed time from system startup time
CLOCK_PROCESS_CPUTIME_IDRunning time of this process
CLOCK_THREAD_CPUTIME_IDThe running time of this thread

Program example

#include <time.h>
#include <stdio.h>
#include <sys/time.h>

int main(void)
{
    struct timespec tsp;

    printf("CLOCK REALTIME time:\n");
    clock_gettime(CLOCK_REALTIME, &tsp);
    printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);
    printf("-----------------------\n");

    printf("CLOCK MONOTONIC time:\n");
    clock_gettime(CLOCK_MONOTONIC, &tsp);
    printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);
    printf("-----------------------\n");

    printf("CLOCK PROCESS CPUTIME ID time:\n");
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tsp);
    printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);
    printf("-----------------------\n");

    printf("CLOCK THREAD CPUTIME ID time:\n");
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tsp);
    printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);
    printf("-----------------------\n");

   
    return 0;
}

Operation results:

CLOCK REALTIME time:
sec:1644155596, nsec:748701786
-----------------------
CLOCK MONOTONIC time:
sec:12526311, nsec:817330221
-----------------------
CLOCK PROCESS CPUTIME ID time:
sec:0, nsec:585929
-----------------------
CLOCK THREAD CPUTIME ID time:
sec:0, nsec:590570

timeval

prototype

struct timeval
{
  __time_t tv_sec;		/* Seconds.  second*/
  __suseconds_t tv_usec;	/* Microseconds.  Microsecond*/
};

explain

This structure only includes seconds and microseconds, and has no other meaning, such as the number of seconds since 1970. Just a storage space. Parameter for gettimeofday.

timezone

prototype

struct timezone
  {
    int tz_minuteswest;		/* Minutes west of GMT. How many minutes is it from Greenwich */
    int tz_dsttime;		/* Nonzero if DST is ever in effect. Daylight saving time status  */
  };

explain

The structure is time zone related information, which is rarely used, and the output parameter of gettimeofday. Generally, we can also directly pass in NULL

gettimeofday

prototype

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

explain

Get the current time, which is UTC time, seconds + microseconds and time zone information since 1970.

Parameter description

parametertypeexplain
tvstruct timeval *UTC, reference time
tzstruct timezone *Current time zone information

Return value

0 is returned for success, and - 1 is returned for failure. The error reason exists in errno.

Program example

#include <time.h>
#include <stdio.h>
#include <sys/time.h>

int main(void)
{
    struct timeval tv;
    struct timezone tz;


    printf("gettimeofday time:\n");
    gettimeofday(&tv, &tz);

    printf("tv_sec:%ld tv_usec:%ld\n", tv.tv_sec, tv.tv_usec);
    printf("tz:%d %d\n", tz.tz_dsttime, tz.tz_minuteswest);
    

    return 0;
}

Operation results:

gettimeofday time:
tv_sec:1644156383 tv_usec:513679
tz:0 0

time_t

prototype

typedef long time_t;

explain

This type is actually long int, which is used to store the number of seconds. It is the input parameter and return value of the time function.

time

prototype

time_t time(time_t *t)

explain

This function will return the number of seconds elapsed since 0:00 on January 1, 1970. If t is a non null pointer, the function will also store the return value in the memory indicated by the T pointer.

Parameter description

parametertypeexplain
ttime_t *Second storage pointer returned

Return value

The number of seconds is returned if successful, and - 1 is returned if failed. The error reason exists in errno.

Program example

#include <time.h>
#include <stdio.h>
#include <sys/time.h>

int main(void)
{

    time_t timep1, timep2;
    timep1 = time(NULL);
    time(&timep2);
    printf("timep1:%ld  timep2:%ld\n", timep1, timep2);


    return 0;
}

Operation results:

timep1:1644157011  timep2:1644157011

tm

prototype

struct tm
{
  int tm_sec;			/* Seconds.	[0-60] (1 leap second) */
  int tm_min;			/* Minutes.	[0-59] */
  int tm_hour;			/* Hours.	[0-23] */
  int tm_mday;			/* Day.		[1-31] */
  int tm_mon;			/* Month.	[0-11] Note: 0 represents January, and so on*/
  int tm_year;			/* Year	- 1900.  This value is the actual year minus 1900*/
  int tm_wday;			/* Day of week.	[0-6] Note: 0 represents Monday, and so on*/
  int tm_yday;			/* Days in year.[0-365]	The number of days from January 1 of each year, where 0 represents January 1, and so on*/
  int tm_isdst;			/* DST.		[-1/0/1] Xia Lingshi identifier*/
};

explain

This type is used to describe the time and date used in the real world, including year, day, hour, minute, second, week, etc. it is the return value of localtime

localtime

prototype

struct tm *localtime(const time_t *timep);

explain

Convert the current seconds indicated by the parameter timep into the time and date representation method used in the real world, and the result is returned.

Parameter description

parametertypeexplain
timeptime_tCurrent UTC seconds

Return value

The year, month, day, hour, minute, second, week, etc. corresponding to the current UTC seconds.

Program example

#include <time.h>
#include <stdio.h>
#include <sys/time.h>

int main(void)
{
    time_t timep;
    struct tm *p;
    timep = time(NULL);
    printf("timep:%ld\n", timep);
    p = localtime(&timep);
  	// Deal with the year and month accordingly
    printf("%d-%d-%d %d:%d:%d \n", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 
                p->tm_hour, p->tm_min, p->tm_sec);
    
    return 0;
}

Operation results:

timep:1644157741
2022-2-6 22:29:1 

localtime_r

In the program example of localtime above, it can be found that the return value of localtime is of type struct tm *, that is, a pointer to type struct tm, which will not cause problems such as memory leakage. This is because the return value of localtime actually points to a static variable, which is the static struct tm type data defined in the static library. Obviously, Because the program uses static variables, the localtime cannot be re entered, that is, it is not ready-made security. It will not bring any hidden dangers to general application scenarios, but it will bring problems to places with high real-time requirements, because calling localtime many times will cause the return value to be overwritten.

For example:

Two threads A and B call the localtime function at the same time:

Time 1: thread A calls the localtime function to get A pointer, and the value stored in tm is updated to value-A

Time 2: thread B calls the localtime function to get a pointer, and the value stored in tm is updated to value-B

Time 3: thread A refers to the pointer returned by localtime (for example, printf outputs A field). At this time, the value in static struct tm is actually value-b, not the expected value-a

Time 4: thread B refers to the pointer returned by localtime. At this time, the value in static struct tm is actually value-b

Therefore, in order to solve the problem that localtime cannot be re entered, localtime appears_ r.

prototype

struct tm *localtime_r(const time_t *timep, struct tm *result);

explain

To call localtime, you only need to pass in the pointing time_ A constant pointer to t;

Call localtime_t not only needs to pass in pointing to time_ A constant pointer to t also needs to pass in a pointer to struct tm, and the result will be stored in the struct tm object pointed to by result;

Program example

#include <time.h>
#include <stdio.h>
#include <sys/time.h>

int main(void)
{
    time_t timep;
    struct tm *p;
    struct tm res;
    timep = time(NULL);
    printf("timep:%ld\n", timep);
    localtime_r(&timep, &res);

    printf("%d-%d-%d %d:%d:%d \n", 1900 + res.tm_year, 1 + res.tm_mon, res.tm_mday, 
                res.tm_hour, res.tm_min, res.tm_sec);

    return 0;
}

Operation results:

timep:1644158806
2022-2-6 22:46:46 

Summary

The above are the definitions of common structures, variables and interfaces related to time under linux platform. For more detailed description, please refer to the relevant source code definitions.

Topics: Linux Operation & Maintenance server