unix系统中的时间值

一、前言

本文将简单介绍unix系统中时间相关的概念,包括日历时间和进程时间两种不同的时间值。

二、日历时间

日历时间是指从1970年1月1日 00:00:00这个时间点开始,到当前所经过的秒数累计值。将这个秒数值经过换算就能得到当前时间。日历时间常用来记录文件最近一次的修改时间。
系统基本数据类型time_t用于保存这种时间值。

2.1 日历时间相关的库函数和系统调用

在Unix系统中,与日历时间相关的库函数和系统调用主要集中在标准C库(libc)和POSIX标准中。以下是一些常用的函数和调用:
1.time()

功能:获取当前时间,返回自纪元以来的秒数
头文件:<time.h>
原型:time_t time(time_t *tloc);

参考代码:

#include <stdio.h>
#include <time.h>
int main() {
    time_t now;
    time(&now);
    printf("The current time is: %ld\n", now);
    printf("The current time is: %s", ctime(&now));
    return 0;
}

运行结果如下所示:
在这里插入图片描述

(2.1-1)
2.localtime()

功能:将time_t类型的时间转换为本地时间的tm结构体。 头文件:<time.h>
原型:struct tm *localtime(const time_t *timep);

先来看下tm结构体的定义:

#include <time.h>

struct tm {
    int tm_sec;    // 秒,范围从 0 到 60(偶尔会出现闰秒)
    int tm_min;    // 分,范围从 0 到 59
    int tm_hour;   // 时,范围从 0 到 23
    int tm_mday;   // 一月中的第几天,范围从 1 到 31
    int tm_mon;    // 月份,范围从 0 到 11(0 表示一月)
    int tm_year;   // 年份,从 1900 年开始的年数
    int tm_wday;   // 一周中的第几天,范围从 0 到 6(0 表示星期天)
    int tm_yday;   // 一年中的第几天,范围从 0 到 365
    int tm_isdst;  // 夏令时标志,正数表示夏令时有效,0 表示无效,负数表示信息不可用
};

参考代码:

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

int main() {
    time_t now;
    struct tm *ltm;
    time(&now);
    ltm = localtime(&now);
    printf("The current time is: %ld\n", now);
    printf("The current time is: %s", ctime(&now));
    printf("The current time is: %d-%d-%d %d:%d:%d %d %d %d\n", ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec,ltm->tm_wday, ltm->tm_yday, ltm->tm_isdst);
    return 0;
}

运行结果如下:
在这里插入图片描述

(2.1-2)
3.gmtime()

功能:将time_t类型的时间转换为UTC时间的tm结构体。 头文件:<time.h>
原型:struct tm *gmtime(const time_t *timep);

参考代码:

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

int main() {
    time_t now;
    struct tm *ltm;
    now = time(NULL);
    ltm = gmtime(&now);
    printf("The current time is: %ld\n", now);
    printf("The current time is: %s", ctime(&now));
    printf("The current time is: %d-%d-%d %d:%d:%d %d %d %d\n", ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec,ltm->tm_wday, ltm->tm_yday, ltm->tm_isdst);
    return 0;
}

运行结果如下所示:
在这里插入图片描述

(2.1-3)
需要注意的是,只有当系统的时间设置为UTC时间,通过该库函数返回的结果才是UTC时间。

4.mktime()

功能:将tm结构体表示的时间转换为time_t类型的时间。 头文件:<time.h>
原型:time_t mktime(struct tm *tm);

参考代码:

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

int main() {
    struct tm ltm;
    time_t current_time;

    ltm.tm_year = 2024 - 1900;
    ltm.tm_mon = 8 - 1;
    ltm.tm_mday = 27;
    ltm.tm_hour = 10;
    ltm.tm_min = 40;
    ltm.tm_sec = 0;
    ltm.tm_isdst = -1;

    current_time = mktime(&ltm);

    printf("The current time is: %ld\n", current_time);
    printf("The current time is: %s", ctime(&current_time));

    return 0;

}

运行结果如下所示:
在这里插入图片描述

(2.1-4)
5.strftime()

功能:将tm结构体表示的时间格式化为字符串。
头文件:<time.h>
原型:size_t strftime(char *s, size_t
max, const char *format, const struct tm *tm);

参考代码:

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

int main()
{
    time_t current_time;
    struct tm *ltm;
    char time_str[50];

    time(&current_time);
    ltm = localtime(&current_time);
    strftime(time_str, sizeof(time_str), "%Y-%m-%d_%H:%M:%S", ltm);

    printf("The current time is: %ld\n", current_time);
    printf("The current time is: %d-%d-%d %d:%d:%d %d %d %d\n", ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec,ltm->tm_wday, ltm->tm_yday, ltm->tm_isdst);
    printf("The current time is: %s\n", time_str);

    return 0;
}

运行结果如下:
在这里插入图片描述

(2.1-5)
6.ctime()

功能:将time_t类型的时间转换为可读的字符串格式。
头文件:<time.h>
原型:char *ctime(const time_t *timep);

上面的参考代码中已经包含了此用例。

上面的是库函数,接下来将介绍的是系统调用:
7.gettimeofday()

功能:获取当前时间,包括秒和微秒
头文件:<sys/time.h>
原型:int gettimeofday(struct timeval *tv, struct timezone *tz);

这里的timeval结构定义如下:

#include <sys/time.h>

struct timeval {
    time_t      tv_sec;     // 秒
    suseconds_t tv_usec;    // 微秒
};

参考代码:

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

int main()
{
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv, &tz);
    printf("The current time is: %ld.%ld %d\n", tv.tv_sec, tv.tv_usec, tz.tz_dsttime);
    printf("%s", ctime(&tv.tv_sec));
    return 0;
}

运行结果如下所示:
在这里插入图片描述

(2.1-6)
8.settimeofday()

功能:设置系统时间和时区。
头文件:<sys/time.h>
原型:int settimeofday(const struct timeval *tv, const struct timezone *tz);

参考代码:

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

int main()
{
    struct timeval tv;
    struct timezone tz;
    gettimeofday(&tv, &tz);
    printf("The current time is: %ld.%ld %d\n", tv.tv_sec, tv.tv_usec, tz.tz_dsttime);
    printf("%s", ctime(&tv.tv_sec));

    tv.tv_sec += 180;
    if(settimeofday(&tv, NULL) == -1) {
        perror("settimeofday");
        return 1;
    }

    gettimeofday(&tv, &tz);
    printf("The new time is: %ld.%ld %d\n", tv.tv_sec, tv.tv_usec, tz.tz_dsttime);
    printf("%s", ctime(&tv.tv_sec));
    return 0;
}

运行结果如下所示:
在这里插入图片描述

(2.1-7)
提示我们没有权限去修改系统的时间。可以尝试使用root用户来执行程序,即加上sudo。

9.clock_gettime()

功能:获取高精度时间。
头文件:<time.h>
原型:int clock_gettime(clockid_t clk_id, struct
timespec *tp);

- clk_id:表示要获取的时钟类型,常用的时钟类型包括:
  - CLOCK_REALTIME:系统实时时间,从Epoch(1970年1月1日00:00:00 UTC)开始计算。
  - CLOCK_MONOTONIC:单调递增的时间,不受系统时间调整的影响。
  - CLOCK_PROCESS_CPUTIME_ID:进程的CPU时间。
  - CLOCK_THREAD_CPUTIME_ID:线程的CPU时间。
- tp:指向 struct timespec 结构体的指针,用于存储返回的时间值。
返回值
- 成功时返回0。
- 失败时返回-1,并设置 errno 以指示错误类型。
struct timespec 结构体
struct timespec 结构体用于表示时间,包括秒和纳秒:
struct timespec {
    time_t   tv_sec;        // 秒
    long     tv_nsec;       // 纳秒
};

10.clock_settime()

功能:设置高精度时间。
头文件:<time.h>
原型:int clock_settime(clockid_t clk_id, const
struct timespec *tp);

三、进程时间

进程时间也被称为cpu时间,是用来度量进程使用的中央处理器资源的时间。简单来说,就是进程从开始到结束这段时间里,处理器用于处理该进程的时间片的总和。进程时间以时钟滴答计算,也就是说进程时间是通过时钟来计算的。
系统基本类型clock_t用于保存这种时间值。
当度量一个进程的执行时间时,unix系统用3个进程时间值来维护:时钟时间、用户cpu时间,系统cpu时间。
时钟时间:是进程运行的时间总量,其值与系统中同时运行的进程数有关。
用户cpu时间:用户cpu时间指执行用户指令的时间,也就是执行内核操作以外的时间。
系统cpu时间:指为该进程执行内核程序所用的时间。
用户cpu时间和系统cpu时间被称为cpu时间。一般cpu时间是小于时钟时间的,因为同一时间系统一般都不仅有一个进程在运行。

3.1 如何获取进程时间

要取得任意进程的进程时间,可以直接通过time命令,如下所示:
在这里插入图片描述

(3.1-1)
从上图所示,时钟时间大于cpu时间。

参考资料:

《UNIX环境高级编程(第3版) (史蒂文斯 (W.Richard Stevens) 拉戈 (Stephen A.Rago))
(Z-Library)》

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值