Linux中的时间编程

Linux中的时间编程

前言

在Linux的应用编程或者内核编程中,我们经常会用到一些简单的软件延时,今天就来学习一些这些延时的使用方法。前面两部分是延时函数,后面是Linux时间编程。

一、sleep系统函数

sleep函数是在系统编程时使用的函数,或者说是在进行Linux应用编程才使用的。简单介绍如下:

1.1 sleep秒延时

函数原型:

unsigned int sleep(unsigned int seconds);

返回值说明:返回无符号的整形数值,如果延时成功则返回 0,如果延时过程中被打断,则返回剩余的秒数。

例如 sleep(5),返回值为 3,那么实际延时就是 5-3=2 秒。

1.2 usleep微秒延时

u前缀即说明这个是us级的延时函数,函数原型:

int usleep(useconds_t usec);

参数:usec需要<1000000

返回值:延时成功返回0,失败直接返回-1

例如:usleep(10),表示延时 10 微秒

简单示例:

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

int main(int argc, char *argv[])
{
    while(1)
    {
        printf("LED ON!\n");
        if(sleep(1))
            printf("sleep(1) failed!\n");
        if(usleep(1000))
            printf("usleep(1000) failed!\n");
            
        printf("LED OFF!\n");
        if(sleep(1))
            printf("sleep(1) failed!\n");
        if(usleep(1000))
            printf("usleep(1000) failed!\n");
    }

    exit(0);
}

编译测试,执行后大约2s打印输出一次LED状态。

sleep/usleep

二、delay内核函数

delay系列函数是在内核中使用的,当我们进行驱动编写或者硬件初始化时序时会用到一些。下面是delay函数的简单介绍。

2.1 mdelay毫秒延时

m前缀即表示毫秒延时,函数原型:

void mdelay(unsigned long msecs);

使用示例:mdelay(10),表示延时 10 毫秒。

2.2 udelay微秒延时

u前缀即表示微秒延时,函数原型:

void udelay(unsigned long usecs);

使用示例:udelay(10),表示延时 10 us。

2.2 ndelay纳秒延时

n前缀即表示纳秒延时,函数原型:

void ndelay(unsigned long nsecs);

使用示例:ndelay(10),表示延时 10 ns。

说明

Linuxux下的延时函数主要有sleepusleepndelayudelaymdelay等,

Linux 系统编程下用到的延时函数在头文件“#include <unistd.h>”中,包括函数 sleepusleep
Linux 内核中用到的延时函数在“#include <linux/delay.h>”中,包括函数 ndelayudelaymdelay

特别注意要分开内核编程和系统编程中使用的延时函数,这两类函数是不能混用的。

三、Linux时间

在Linux中有几个时间需要进行区分,UTC时间、UNIX纪元时间、格林尼治标准时间(GMT)。

UTC时间即世界统一时间;

Unix 纪元时间是指从 1970 年 1 月 1 日 00:00:00 UTC 开始所经过的秒数,也叫机器日历时间;

GMT 是指太阳经过英国格林尼治的时间。在英国很 NX 的时候,以格林尼治为 0 度经线,
将世界分为 24 个时区。

在Linux中时间日期使用Unix纪元时间的方式,有效位是秒。

3.1 时间函数

3.1.1 time函数

time函数在头文件“#include <time.h>” 声明 ,通过time函数可以获取UTC时间,单位为秒s。

函数原型:

time_t time(time_t *t);

time_t是long类型的整数,参数t可以省略设置为NULL,此时会返回当前的日历时间(秒单位);当传递参数给t时,获取到的日历时间会传递给该参数,此时返回值-1代表失败,返回0。简单代码示例:

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

int main(int argc, char **argv)
{
    time_t Ntime;
    if(time(&Ntime) > 0)
        printf("time: 0x%lx\n", Ntime);

    sleep(1);//延时1s
    Ntime = time(NULL);
    printf("time: 0x%lx\n", Ntime);

    exit(0);
}

结果:
在这里插入图片描述
注意:当time传入空参数时,NULL必不可少,否则会报错。

3.1.2 gettimeofday/settingofday函数

time() 函数获取的是s级的时间,要获取更高精度的时间,可以通过两个高精度的时间函数,gettimeofday/settingofday函数,这两个函数需要包含的头文件为`#include <sys/time.h>` 。

函数原型分别为:

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

结构体timeval

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

结构体timezone

struct timezone {
    int tz_minuteswest;/* minutes west of Greenwich,格林威治时间的时差 */
    int tz_dsttime;/* type of DST correction,时间修正的方式 */
};

gettimeofday()用于获取当前的时间,可以获取到秒、微秒级时间,settimeofday()则用于设置当前系统的时间,可以设置的也是秒、微秒级的时间,timezone是时区,可以传入NULL

代码示例:

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

void loop(void)
{
    int i,j;
    for(i=0;i<10;i++)
        for(j=0;j<10;j++);
}

int main(int argc, char **argv)
{
    struct timeval tim1;
    struct timeval tim2; 
    struct timeval Stim;

    gettimeofday(&tim1, NULL);
    printf("tim1->tv_usec: %ld\n", tim1.tv_usec);
    loop();
    gettimeofday(&tim2, NULL);
    printf("tim2->tv_usec: %ld\n", tim2.tv_usec);   

    printf("tim2-tim1= %ldus\n",tim2.tv_usec-tim1.tv_usec);

    Stim.tv_sec = 0;
    Stim.tv_usec = 100;
    settimeofday(&Stim, NULL);
    printf("after set time,the time is:%lds %lds\n", Stim.tv_sec, Stim.tv_usec);
    
    return 0;
}

输出结果:
在这里插入图片描述

3.2 时间转换

上面获取到的时间的格式是16进制的,为了直观一点,可以使用时间转换函数,对时间数据进行格式转换。下面介绍方法。

3.2.1 时间结构体

常用时间结构体tm

struct tm{
    int tm_sec; 
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon; 
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;
};

成员说明:

  • int tm_sec; 秒 – 取值区间为[0,59]。
  • int tm_min; 分 - 取值区间为[0,59]。
  • int tm_hour; 时 - 取值区间为[0,23]。
  • int tm_mday;一个月中的日期 - 取值区间为[1,31]。
  • int tm_mon;月份(从一月开始,0 代表一月) - 取值区间为[0,11]。
  • int tm_year;年份,其值等于实际年份减去 1900。
  • int tm_wday;星期 – 取值区间为[0,6],其中 0 代表星期天,1 代表星期一,以此类推 。
  • int tm_yday;从每年的 1 月 1 日开始的天数 – 取值区间为[0,365],其中 0 代表 1 月 1 日,1 代表 1 月 2 日,以此类推。
  • int tm_isdst; 夏令时标识符,实行夏令时的时候,tm_isdst 为正。不实行夏令时的进候,tm_isdst 为 0;不了解情况时,tm_isdst()为负
3.2.2 转换函数
  • ctime函数

    ctime函数可以把时间转换为字符串格式,返回值即为转换后的字符串指针。

    函数原型:

    char *ctime(const time_t *timep);
    
  • gmtime函数

    gmtime函数将时间转换为GMT格林尼治时间,保存为上面我们说到的tm类型中。

    函数原型:

    struct tm *gmtime(const time_t *timep);
    
  • asctime函数

    asctime函数也是转换为字符串,但是传入的参数是tm结构体。

    函数原型:

    char *asctime(const struct tm *tm);
    
  • localtime函数

    localtime函数将时间转换为本地时间,函数原型:

    struct tm *localtime(const time_t *clock);
    

    代码示例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    int main(int argc, char **argv)
    {
        time_t Ntime,Ltime;
    
        struct tm *tmStruct = NULL,*localtm = NULL;
        if(time(&Ntime) >= 0)
            printf("time():0x%lx\n", Ntime);
        printf("--------------------------------\n");
        printf("ctime(): %s\n", ctime(&Ntime));
        printf("--------------------------------\n");
        if((tmStruct = gmtime(&Ntime)) != NULL)
        {
            printf("gmtime sec: %d\n", tmStruct->tm_sec);
            printf("gmtime min: %d\n", tmStruct->tm_min);
            printf("gmtime hour: %d\n", tmStruct->tm_hour);
            printf("gmtime mday: %d\n", tmStruct->tm_mday);
            printf("gmtime mon: %d\n", tmStruct->tm_mon+1);
            printf("gmtime year: %d\n", tmStruct->tm_year+1900);
            printf("gmtime wday: %d\n", tmStruct->tm_wday);
            printf("gmtime yday: %d\n", tmStruct->tm_yday);
            printf("gmtime isdst: %d\n", tmStruct->tm_isdst);
        }
        printf("--------------------------------\n");
        printf("asctime(gmtime): %s\n", asctime(tmStruct));
        printf("--------------------------------\n");
        time(&Ltime);
        if((localtm = localtime(&Ltime)) != NULL)
        {
            printf("gmtime sec: %d\n", localtm->tm_sec);
            printf("gmtime min: %d\n", localtm->tm_min);
            printf("gmtime hour: %d\n", localtm->tm_hour);
            printf("gmtime mday: %d\n", localtm->tm_mday);
            printf("gmtime mon: %d\n", localtm->tm_mon+1);
            printf("gmtime year: %d\n", localtm->tm_year+1900);
            printf("gmtime wday: %d\n", localtm->tm_wday);
            printf("gmtime yday: %d\n", localtm->tm_yday);
            printf("gmtime isdst: %d\n", localtm->tm_isdst);
        }
        printf("localtime():%s", asctime(localtm));
    
        exit(0);
    }
    

    执行结果:

    在这里插入图片描述

注意:转换函数的参数需要经过time()进行获取,然后才可以进行转换,否则容易出现错误导致时间不对。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值