Introduce related operations of time processing under Linux (RTC, delay, alarm clock, conversion)

1. System time setting

This article mainly introduces the related functions and operations of time processing under Linux. For example: system time setting, reading, RTC time setting, reading, time unit conversion, delay function, alarm signal, etc.

There are two kinds of time under Linux: 1. System time, 2. RTC time

The system time is read and set from the RTC driver every time the operating system is started. Generally, it will only be automatically synchronized (startup script) once when the system is powered on and started. Subsequent users can also synchronize again through specific commands; in The time seen on the system interface is the system time; the system time will be lost every time the system is shut down and needs to be obtained from the RTC driver every time the system is powered on.

The method to set the system time is as follows: Administrator rights are required

[wbyq@wbyq linux_c]$ date -s "2020-10-12 9:28:20"
date: 无法设置日期: 不允许的操作
2020年 10月 12日 星期一 09:28:20 CST
[wbyq@wbyq linux_c]$ sudo date -s "2020-10-12 9:28:20"
[sudo] password for wbyq: 
2020年 10月 12日 星期一 09:28:20 CST
[wbyq@wbyq linux_c]$ 

The RTC will not stop running when the power is off. The power supply is provided by the backup power supply alone. It can run all the time to provide accurate time to the system.

RTC time reading and setting method: administrator rights are required

hwclock -r   显示RTC时间 (读取RTC时间显示)
hwclock -w   设置RTC时间 (将系统时间传递给RTC驱动,设置RTC的驱动时间)
hwclock -s   设置系统时间(将RTC时间读取出来设置给系统时间)

This can also be achieved through code:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/rtc.h>

/*
RTC_SET_TIME
RTC_RD_TIME
*/

struct rtc_time time;
int main(int argc,char **argv)
{
    if(argc!=2)
    {
        printf("./app /dev/rtcX\n");
        return 0;
    }
    //1.打开设备文件
    int fd=open(argv[1],2);
    if(fd<2)
    {
        printf("%s 设备文件打开失败.\n",argv[1]);
        return 0;
    }
    
    //2.获取RTC驱动的时间
    ioctl(fd,RTC_RD_TIME,&time);
    printf("应用层读取的时间: %d-%d-%d %d:%d:%d\n",
            time.tm_year+1900,
            time.tm_mon+1,
            time.tm_mday,
            time.tm_hour,
            time.tm_min,
            time.tm_sec);
    
    //3.设置RTC驱动的时间
    time.tm_year=2021-1900;
    time.tm_mon=10-1;
    time.tm_mday=1;
    time.tm_hour=11;
    time.tm_min=10;
    time.tm_sec=20;
    ioctl(fd,RTC_SET_TIME,&time);
    
    //4. 关闭驱动
    close(fd);
    return 0;
}

2. Introduction to time processing related functions (time.h)

#include <time.h>
struct tm {
    int tm_sec;         /* seconds */
    int tm_min;         /* minutes */
    int tm_hour;        /* hours */
    int tm_mday;        /* day of the month */
    int tm_mon;         /* month */
    int tm_year;        /* year */
    int tm_wday;        /* day of the week */
    int tm_yday;        /* day in the year */
    int tm_isdst;       /* daylight saving time */
};

char *asctime(const struct tm *tm); //内部有一个全局空间存放转换的时间
char *asctime_r(const struct tm *tm, char *buf); //用户可以指定自己的空间
函数功能: 将tm时间结构体里的时间转为字符串格式返回(指针返回).

char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
函数功能: 将秒单位的时间转为字符串格式返回.

struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
函数功能: 将秒单位的时间转为格林威治时间返回---使用tm结构体。

struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
函数功能: 将秒单位的时间转为本地时间返回.---使用tm结构体

time_t mktime(struct tm *tm);
函数功能: 将tm结构体时间转为秒单位返回.

time_t time(time_t *t);
函数功能:如果形参填NULL就表示获取当期系统的秒单位时间.

size_t strftime(char *s, size_t max, const char *format,
                       const struct tm *tm);
函数功能:  将tm结构体的时间按照指定的格式转成字符串返回.
const char *format 格式有以下格式可以填:
%H 小时(以 00-23 来表示)
%M 分钟(以 00-59 来表示)
%S 秒(以本地的惯用法来表示)
%Y 年份(以四位数来表示)
%m 月份(以 01-12 来表示)
%d 日期(以 01-31 来表示)。

Time acquisition and conversion example:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc,char **argv)
{
    /*1.获取本地的秒单位时间*/
    time_t sec_time=time(NULL);
    printf("当前系统的总秒数:%d\n",sec_time);
    /*2. 将秒单位时间转为字符串返回*/
    char time_buff[100];
    ctime_r(&sec_time,time_buff);
    printf("字符串格式时间(系统默认):%s\n",time_buff);
    /*3. 将秒单位时间转为tm结构体返回*/
    struct tm tm_time;
    gmtime_r(&sec_time,&tm_time);
    printf("国际时间: %d-%d-%d %d:%d:%d\n",tm_time.tm_year+1900,
                                 tm_time.tm_mon+1,
                                 tm_time.tm_mday,
                                 tm_time.tm_hour,
                                 tm_time.tm_min,
                                 tm_time.tm_sec);

    localtime_r(&sec_time,&tm_time);
    printf("本地时间: %d-%d-%d %d:%d:%d\n",tm_time.tm_year+1900,
                                 tm_time.tm_mon+1,
                                 tm_time.tm_mday,
                                 tm_time.tm_hour,
                                 tm_time.tm_min,
                                 tm_time.tm_sec);
    /*4. 将tm结构体时间转为秒单位返回.*/
    printf("总秒数:%d\n",mktime(&tm_time));

    /*5. 将tm结构体时间格式按照指定格式转为字符串*/
    strftime(time_buff,sizeof(time_buff),"%Y_%m_%d_%H_%M_%S.mp4",&tm_time);
    printf("time_buff=%s\n",time_buff);

    return 0;
}

3. Some commonly used delay functions

#include <unistd.h>
unsigned int sleep(unsigned int seconds);
函数功能: 秒单位的延时函数.

int usleep(useconds_t usec);
函数功能: 微秒单位的延时函数.

#include <time.h>
int nanosleep(const struct timespec *req, struct timespec *rem);
函数功能: 秒+纳秒的延时函数.

struct timespec {
    time_t tv_sec;        /* seconds */
    long   tv_nsec;       /* nanoseconds */
};

以上的函数都是可中断的延时函数。 
比如: 延时10秒,有可能10秒钟还没有到达,它可以被其他信号终止.

Sample code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

int main(int argc,char **argv)
{
    printf("1234\n");
    //sleep(5);
    //usleep(1000*1000);

    struct timespec req={5,1000}; //将要延时的时间
    struct timespec rem; //保存是延时结束剩余的时间
    nanosleep(&req,&rem);

    printf("5678\n");
    return 0;
}

4. System timer signal: alarm clock signal

Function prototype introduction:

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
闹钟超时之后会产生SIGALRM闹钟信号。

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
函数功能: 捕获进程收到的信号.
函数参数:
int signum 要捕获的信号
sighandler_t handler  捕获信号之后调用的处理函数

Sample code:

例子代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>

void sighandler_func(int sig)
{
    printf("闹钟时间到达.\n");
    //定义一个闹钟
    alarm(1); //重复定时
}

int main(int argc,char **argv)
{
    //声明要捕获的信号
    signal(SIGALRM,sighandler_func);
    //定义一个闹钟
    alarm(1);
    while(1)
    {

    }
    return 0;
}
运行效果:



[wbyq@wbyq linux_c]$ gcc app.c 
[wbyq@wbyq linux_c]$ ./a.out 
闹钟时间到达.
闹钟时间到达.
闹钟时间到达.
闹钟时间到达.
闹钟时间到达.

Guess you like

Origin blog.csdn.net/qq_43416206/article/details/135254225