Linux应用层系统时间写入RTC时钟的方法

Linux内核版本:linux-3.0.35 开发板:i.MX6S MY-IMX6-EK200 系统:Ubuntu12 前言:之前写过一篇关于如何通过应用层程序读取系统时间的blog,今天再写一篇如何写入并保存RTC时钟的blog吧。

一、写入时间 1、预备知识: a、mktime 头文件#include <time.h> 函数time_t mktime(struct tm *timeptr) 函数说明:mktime()用来将timeptr所指的tm结构体数据换成从公元1970年1月1日0时0分0 秒算起至今的本地时间所经过的秒数。 返回值:返回经过的秒数。当发生错误的时候,返回-1。 b、settimeofday 头文件#include <sys/time.h> #include <unistd.h> 函数:int settimeofday(const struct timeval *tv,const struct timezone *tz) 函数说明:settimeofday()会把目前时间设成由tv所指的结构体信息,当地时区信息则设成tz所指的结构体。 返回值:只有root权限才能使用此函数修改时间。成功则返回0,失败返回-1,错误代码存于errno。 2、实践:     通过mktime和settimeofday配合使用,即可完成时间的写入。 3、代码如下:

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <bits/types.h>
#include <linux/rtc.h>

struct my_timeval
{
    __time_t tv_sec;
    __suseconds_t tv_usec;
};

/*************************************************
*函数名       :    System_SetTime
*功能         :    写入系统时间
*使用方法      :    char* dt = "2016-04-15 21:00:00";
                   System_SetTime(dt);
**************************************************/
int System_SetTime(char* dt)
{
    struct rtc_time tm;
    struct tm _tm;
    struct my_timeval tv;
    time_t timep;

    sscanf(dt,"%d-%d-%d %d:%d:%d",&tm.tm_year,&tm.tm_mon,&tm.tm_mday,&tm.tm_hour,&tm.tm_min,&tm.tm_sec);
    _tm.tm_sec = tm.tm_sec;
    _tm.tm_min = tm.tm_min;
    _tm.tm_hour = tm.tm_hour;
    _tm.tm_mday = tm.tm_mday;
    _tm.tm_mon = tm.tm_mon - 1;
    _tm.tm_year = tm.tm_year - 1900;

    timep = mktime(&_tm);                               
    tv.tv_sec = timep;
    tv.tv_usec = 0;
    if(settimeofday(&tv, (struct timezone *) 0) < 0)
    {
        printf("Set system datetime error!\n");
        return -1;
    }   
    return 0;
}

void main(void)
{
    char *dt = "2016-4-15 21:00:00";
    System_SetTime(dt);
}

4、测试结果:

二、保存时间 从上面的测试结果可以看出,可以正常写入系统时间了。我起初也以为这样就可以了,但是我发现,这样是不行的。因为一旦我重新启动开发板,系统时间又会回复到原来的时间。想想也是,我们只是写入了系统时间,没有将系统时间同步到硬件时间,这样系统每次重启读取的硬件时间是没有改变的,启动后得到的系统时间CST = UTC + 8,还是换来的系统时间。那怎样将我们设置的系统时间同步到硬件时间呢?我们知道在终端里,可以通过hwclock –systohc将系统时间同步到硬件时间上去,在应用层怎么实现呢?我不知道有没有其他好的解决办法,我想出来的办法就是在应用层创建子进程,在子进程里调用脚本文件,脚本里的指令就是hwclock –systohc。这样就完成了同步。当然如果有更简单和更合适的方法,欢迎指导、交流。说了这么多,言归正传。 1、预备知识: a、fork创建子进程,代码如下:

/**************************
*功能:创建子进程fork()测试
*时间:2016-4-15
*作者:Jack Cui
***************************/
#include <unistd.h>
#include <stdio.h> 
int main (void) 
{ 
    pid_t fpid;                 //fpid表示fork函数返回的值
    int count=0;
    fpid=fork(); 
    if (fpid < 0)               //创建子进程失败
        printf("error\n"); 
    else if (fpid == 0) {
        printf("I am the child process,my process id is %d\n",getpid()); 
        count++;
    }
    else {
        printf("I am the parent process,my process id is %d\n",getpid()); 
        count++;
    }
    printf("count = %d\n",count);
    return 0;
}

b、fork测试程序结果显示:

c、execve()应用层调用脚本文件: 头文件:#include <unistd.h> 函数:int execve(const char * filename, char * const argv[], char * const envp[]); 函数说明: execve()用来执行参数filename 字符串所代表的文件路径, 第二个参数系利用数组指针来传递给执行文件, 最后一个参数则为传递给执行文件的新环境变量数组。 返回值:如果执行成功则函数不会返回, 执行失败则直接返回-1, 失败原因存于errno 中。 d、execve()测试代码:

/**************************
*功能:测试execve
*时间:2016-4-15
*作者:Jack Cui
***************************/

#include <stdio.h>         //perror
#include <stdlib.h>        //EXIT_SUCCESS EXIT_FAILURE
#include <unistd.h>        //execve

void main(void)
{
    char * args[] = {"/home/nfsroot/hwclock.sh", NULL};
    if(-1 == (execve("/home/nfsroot/hwclock.sh",args,NULL)))
    {
        perror("execve");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

e、脚本内容:

f、execve测试结果:

    可以看出execve使用正常,我们将脚本内容改为hwclock –systohc就可以实现将系统时间同步到硬件时间了。 三、整体代码如下:

/******************************************
*功能:Linux应用层系统时间写入RTC时钟的方法
*时间:2016-4-15
*作者:Jack Cui
*******************************************/

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <bits/types.h>
#include <linux/rtc.h>

struct my_timeval
{
    __time_t tv_sec;
    __suseconds_t tv_usec;
};

/*************************************************
*函数名        :   System_SetTime
*功能         :   写入系统时间
*使用方法   :   char* dt = "2016-04-15 21:00:00";
                System_SetTime(dt);
**************************************************/
int System_SetTime(char* dt)
{
    struct rtc_time tm;
    struct tm _tm;
    struct my_timeval tv;
    time_t timep;

    sscanf(dt,"%d-%d-%d %d:%d:%d",&tm.tm_year,&tm.tm_mon,&tm.tm_mday,&tm.tm_hour,&tm.tm_min,&tm.tm_sec);
    _tm.tm_sec = tm.tm_sec;
    _tm.tm_min = tm.tm_min;
    _tm.tm_hour = tm.tm_hour;
    _tm.tm_mday = tm.tm_mday;
    _tm.tm_mon = tm.tm_mon - 1;
    _tm.tm_year = tm.tm_year - 1900;

    timep = mktime(&_tm);                               
    tv.tv_sec = timep;
    tv.tv_usec = 0;
    if(settimeofday(&tv, (struct timezone *) 0) < 0)
    {
        printf("Set system datetime error!\n");
        return -1;
    }   
    return 0;
}

void main(void)
{
    char *dt = "2016-4-15 21:00:00";
    pid_t fpid;                 //fpid表示fork函数返回的值
    fpid=fork(); 
    if (fpid < 0)               //创建子进程失败
        printf("error\n"); 
    else if (fpid == 0) 
    {
        char * args[] = {"/home/nfsroot/hwclock.sh", NULL};
        if(-1 == (execve("/home/nfsroot/hwclock.sh",args,NULL)))
        {
            perror("execve");
            exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
    }
    else
    {
        System_SetTime(dt);
    }
    return 0;
}

四、最终结果显示: 1、脚本内容:

2、测试结果:

这样我们重新启动开发板,系统时间不会变,设置成功~!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏分布式系统进阶

Kafka集群Metadata管理Kafka源码分析-汇总

可以看到是调用了ReplicaManager.maybeUpdateMetadataCache方法, 里面又会调用到MetadataCache.updateCa...

1592
来自专栏Android相关

处理器结构--ReorderBuffer

Reorder Buffer用来保存在乱序执行之前的(OOOE)指令执行顺序,当指令集合在乱序执行后按照原有指令顺序将结果提交。

1144
来自专栏技术墨客

Spring核心——Bean的依赖注入 原

在设计模式与IoC这篇文章中,介绍了Spring基础的三大支柱的两项内容——IoC、Bean。本篇将继续围绕着Bean的创建时的注入方式来介绍Spring的核心...

821
来自专栏芋道源码1024

注册中心 Eureka 源码解析 —— EndPoint 与 解析器

目前有多种 Eureka-Server 访问地址的配置方式,本文只分享 Eureka 1.x 的配置,不包含 Eureka 1.x 对 Eureka 2.x 的...

990
来自专栏开源优测

[接口测试 - http.client篇] 16 基于http.client之POM实战一下

概述 关注公众号回复: http.client_pom_demo 获取本文示例源码 你需要了解以下知识和技术,以便掌握后续的实例代码: http.client常...

3528
来自专栏GreenLeaves

WebService 之 身份验证

  在项目开发,我们经常会使用WebService,但在使用WebService时我们经常会考虑到了WebService是安全问题,很容易想到通过一组用户名与密...

2437
来自专栏aoho求索

Spring Cloud Bus中的事件的订阅与发布(一)

年前最后一篇文章,提前祝大家新年快乐! 下面进入正文。Spring Cloud Bus用轻量级的消息代理将分布式系统的节点连接起来。这可以用来广播状态的该表(比...

38610
来自专栏芋道源码1024

面试问烂的 Spring AOP 原理

来源:https://www.jianshu.com/p/e18fd44964eb

1564
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第十一天 JSP学习

JSP全名是Java Server Pages,它是建立在Servlet规范之上的动态网页开发技术。在JSP文件中,HTML代码与Java代码共同存在,其中,H...

1213
来自专栏扎心了老铁

springboot mybatis 事务管理

本文主要讲述springboot提供的声明式的事务管理机制。 一、一些概念 声明式的事务管理是基于AOP的,在springboot中可以通过@Transacti...

4537

扫码关注云+社区