Приобретение и использование времени Linux

задняя часть Linux Безопасность C++
Приобретение и использование времени Linux

Существует два типа системного времени Linux.

(1) Календарное время. Значение представляет собой совокупное количество секунд, прошедших с определенного времени 1 января 1970 года, 00:00:00 по всемирному координированному времени (UTC). основные типы данныхtime_tспасти. Наконец, с помощью преобразования мы можем получить 24-часовое или 12-часовое время, которое мы обычно видим.

(2) Время обработки. Также известное как процессорное время, оно измеряет ресурсы ЦП, используемые процессом. Время обработки измеряется в тактах часов.

календарное время

time() получает метку времени

Функция времени используется для получения временной метки календарного времени, которое представляет собой количество секунд с 0:00 1 января 1970 г. (00:00:00 UTC, 1 января 1970 г.).

Функция определяется следующим образом:

#include <time.h>
time_t time(time_t *calptr)
  • timeВозвращает временную метку текущего времени, которая представляет собой количество секунд с момента всемирного времени;
  • time_tТип временной метки, определенный реальной системой. Функция возвращает текущую временную метку в обычном режиме и возвращается в случае сбоя.(time_t)-1;
  • calptrЕсли он не пуст, в этот указатель также будет записана метка времени;

Пример вызова:

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

using namespace std;

int main()
{
	time_t curTime;
	curTime = time(NULL);
	cout << curTime << endl;
	return 0;
}

результат: Возвращает строку значений, например1533287924

gettimeofday() и clock_gettime() получают более точное время

timeФункция может получить время только с точностью до секунды, чтобы получить отметку времени с более высокой точностью, необходимы другие функции.gettimeofdayФункция может получить метку времени с микросекундной точностью, используя структуруtimevalсохранить;clock_gettimeФункция может получить метку времени с точностью до наносекунды, используя структуруtimespecсохранить.

#include <sys/time.h>

int gettimeofday(struct timeval *tp, void *tzp);
因为历史原因tzp的唯一合法值是NULL,因此调用时写入NULL即可。

int clock_gettime(clockid_t clock_id, strcut timespec *tsp);
clock_id有多个选择,当选择为CLOCK_REALTIME时与time的功能相似,但是时间精度更高。

Структуры, используемые этими двумя функциями, определяются следующим образом:

struct timeval
{
    long tv_sec; /*秒*/
    long tv_usec; /*微秒*/
};

struct timespec
{
	time_t tv_sec;  //秒
	long tv_nsec;   //纳秒
};

Пример вызова:

#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <stdlib.h>

using namespace std;

int main()
{
	time_t dwCurTime1;
	dwCurTime1 = time(NULL);

    struct timeval stCurTime2;
    gettimeofday(&stCurTime2, NULL);

    struct timespec stCurTime3;
    clock_gettime(CLOCK_REALTIME, &stCurTime3);

    cout << "Time1: " << dwCurTime1 << "s" << endl;
    cout << "Time2: " << stCurTime2.tv_sec << "s, " << stCurTime2.tv_usec << "us" << endl;
    cout << "Time3: " << stCurTime3.tv_sec << "s, " << stCurTime3.tv_nsec << "ns" << endl;

	return 0;
}

результат:

编译时要在编译命令最后加上-lrt链接Real Time动态库,如
g++ -o time2 test_time_linux_2.cpp -lrt

Time1: 1533289490s
Time2: 1533289490s, 133547us
Time3: 1533289490s, 133550060ns

Визуализируйте временные метки, преобразованные в дни/месяцы/годы

тм структура

Полученная временная метка не может визуально отображать текущее время, поэтому необходимо использоватьtmСтруктура используется для представления времени, которое мы видим каждый день.Структура определяется следующим образом:

struct tm
{
    int tm_sec;  /*秒,正常范围0-59, 但允许至61*/
    int tm_min;  /*分钟,0-59*/
    int tm_hour; /*小时, 0-23*/
    int tm_mday; /*日,即一个月中的第几天,1-31*/
    int tm_mon;  /*月, 从一月算起,0-11*/  1+p->tm_mon;
    int tm_year;  /*年, 从1900至今已经多少年*/  1900+ p->tm_year;
    int tm_wday; /*星期,一周中的第几天, 从星期日算起,0-6*/
    int tm_yday; /*从今年1月1日到目前的天数,范围0-365*/
    int tm_isdst; /*日光节约时间的旗标*/
};

преобразовать time_t в tm

gmtimeиlocaltimeможетtime_tвведите отметку времени дляtmструктура, используемая следующим образом:

struct tm* gmtime(const time_t *timep);
//将time_t表示的时间转换为没有经过时区转换的UTC时间,是一个struct tm结构指针

stuct tm* localtime(const time_t *timep);
//和gmtime功能类似,但是它是经过时区转换的时间,也就是可以转化为北京时间。

Время печати фиксированного формата

получитьtmПосле структуры вы можете преобразовать ее во время повседневного использования в строковом формате или непосредственно изtime_tДля преобразования вы можете использовать следующие две функции для достижения цели. Однако эти две функции могут печатать время только в фиксированном формате.

//这两个函数已经被标记为弃用,尽量使用后面将要介绍的函数
char *asctime(const struct tm* timeptr);
char *ctime(const time_t *timep);

Пример вызова:

#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <stdlib.h>

using namespace std;

int main()
{
	time_t dwCurTime1;
	dwCurTime1 = time(NULL);

    struct tm* pTime;
    pTime = localtime(&dwCurTime1);

    char* strTime1;
    char* strTime2;
    strTime1 = asctime(pTime);
    strTime2 = ctime(&dwCurTime1);

    cout << strTime1 << endl;
    cout << strTime2 << endl;

	return 0;
}

результат:

Fri Aug  3 18:24:29 2018
Fri Aug  3 18:24:29 2018

Гибкая и безопасная функция преобразования времени strftime()

Вышеупомянутые две функции помечены как устаревшие из-за возможных проблем с переполнением буфера, поэтому более безопасным подходом является использованиеstrftimeметод.

/*
** @buf:存储输出的时间
** @maxsize:缓存区的最大字节长度
** @format:指定输出时间的格式
** @tmptr:指向结构体tm的指针
*/
size_t strftime(char* buf, size_t maxsize, const char *format, const struct tm *tmptr);

Мы можем вывести информацию о времени, хранящуюся в timeptr, в buf в форме, заданной форматом, в соответствии с форматом в строке, на которую указывает формат, и сохранить до максимального размера символов в буфере buf. Эта функция возвращает количество символов, помещенных в строку, на которую указывает buf.

Работа функции strftime() чем-то похожа на работу sprintf(): она распознает набор команд форматирования, начинающихся со знака процента (%), а отформатированный вывод помещается в строку. Команда форматирования указывает точное представление различной информации о дате и времени в строке strDest. Остальные символы в строке формата помещаются в строку как есть. Команды формата перечислены ниже, и они чувствительны к регистру.

%a 星期几的简写
%A 星期几的全称
%b 月分的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的后两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中,十进制表示的每月的第几天
%F 年-月-日
%g 年份的后两位数字,使用基于周的年
%G 年分,使用基于周的年
%h 简写的月份名
%H 24小时制的小时
%I 12小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%n 新行符
%p 本地的AM或PM的等价显示
%r 12小时的时间
%R 显示小时和分钟:hh:mm
%S 十进制的秒数
%t 水平制表符
%T 显示时分秒:hh:mm:ss
%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)
%U 第年的第几周,把星期日做为第一天(值从0到53)
%V 每年的第几周,使用基于周的年
%w 十进制表示的星期几(值从0到6,星期天为0)
%W 每年的第几周,把星期一做为第一天(值从0到53)
%x 标准的日期串
%X 标准的时间串
%y 不带世纪的十进制年份(值从0到99)
%Y 带世纪部分的十制年份
%z,%Z 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号

Пример вызова:

#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <stdlib.h>

using namespace std;

int main()
{
	time_t dwCurTime1;
	dwCurTime1 = time(NULL);

    struct tm* pTime;
    pTime = localtime(&dwCurTime1);

    char buf[100];

    strftime(buf, 100, "time: %r, %a %b %d, %Y", pTime);

    cout << buf << endl;

	return 0;
}

результат:

time: 08:18:12 PM, Fri Aug 03, 2018

mktime преобразует struct tm в метку времени time_t

В бизнес-программах часто бывает необходимо сравнить временную последовательность.Если время сравнивается в строковом формате, необходимо убедиться, что формат полностью согласован, а также проблематично преобразовать в строковый формат.Поэтому временные метки часто используется для сравнения. Иногда необходимо преобразовать время в виде строки или время, представленное структурой tm, в метку времени time_t.Это преобразование реализуется функцией mktime.

Прежде чем представить функцию mktime, давайте взглянем на яму, скрытую в структуре struct tm.

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

int main()
{
	time_t tCurTime = time(NULL);
	printf("tCurTime: %lu\n", (unsigned long)(tCurTime));

	struct tm* pTm;
	pTm = localtime(&tCurTime);

	printf("year:%d\n", pTm->tm_year);
	printf("mon:%d\n", pTm->tm_mon);
	printf("day:%d\n", pTm->tm_mday);
	printf("hour:%d\n", pTm->tm_hour);
	printf("min:%d\n", pTm->tm_min);
	printf("sec:%d\n", pTm->tm_sec);

	time_t tMkTime;
	tMkTime = mktime(pTm);
	printf("tMkTime:%lu\n", (unsigned long)tMkTime);

	return 0;
}

Текущее время: пятница, 12 апреля, 12:48:40 CST 2019, и результат этой программы:

tCurTime: 1555044520
year:119
mon:3
day:12
hour:12
min:48
sec:40
tMkTime:1555044520

Не знаю, видишь ли ты подвох. Странно то, что печатный месяц на один месяц меньше фактического, а год меньше 1900. Получается, что время, полученное функцией localtime, отсчитывается от 1 января 1900 года, но я так и не разобрался, как появилась лишняя 1 в этом месяце. Однако не забудьте вычесть 1 при преобразовании текущего времени, сохраненного строкой, в метку времени, иначе желаемый результат не будет получен.

#include <time.h>
time_t mktime(struct tm *tm);

Диаграмма взаимосвязи между функциями времени

время обработки

Время процесса — это время, в течение которого процесс использует ЦП после его создания, и время процесса делится на следующие две части:

  • Время ЦП пользователя: время, затраченное на использование ЦП в пользовательском режиме.
  • Время ЦП ядра: время, затраченное на использование ЦП в режиме ядра. Это время требуется для выполнения вызова ядра или другой специальной задачи.

функция часов

Функция часов предоставляет простой интерфейс для получения времени процесса. Она возвращает значение, описывающее общее время процессора (включая время пользователя и время ядра), используемое процессом. Функция определяется следующим образом:

#include <time.h>
clock_t clock(void)
//if error, return -1

Единицей измерения, возвращаемой функцией часов, является CLOCKS_PER_SEC. Разделите возвращаемое значение на эту единицу измерения, чтобы получить количество секунд времени обработки.

функция времени

Функция времени также является функцией времени процесса, которая имеет более конкретное представление времени процесса.Определение функции выглядит следующим образом:

#include <sys/times.h>
clock_t times(struct tms* buf);

struct tms{
	clock_t tms_utime;
	clock_t tms_stime;
	clock_t tms_cutime;
	clock_t tms_cstime;
};

Хотя возвращаемый тип функции времени по-прежнему является clock_t, он отличается от единицы измерения возвращаемого значения функции часов. Возвращаемое значение функции times измеряется в единицах через sysconf(SC_CLK_TCK) чтобы получить.

Полный вариант использования из Руководства по системному программированию Linux выглядит следующим образом:

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

static void displayProcessTime(const char* msg)
{
	struct tms t;
	clock_t clockTime;
	static long clockTick = 0;

	if (msg != NULL) 
	{
		printf("%s\n", msg);
	}

	if (clockTick == 0)
	{
		clockTick = sysconf(_SC_CLK_TCK);
		if (clockTick < 0) return;
	}

	clockTime = clock();
	printf("clock return %ld CLOCKS_PER_SEC (%.2f seconds)\n", (long)clockTime, (double)clockTime/CLOCKS_PER_SEC);
	
	times(&t);
	printf("times return user CPU = %.2f; system CPU = %.2f\n", (double)t.tms_utime / clockTick, (double)t.tms_stime / clockTick);
}

int main()
{
	printf("CLOCKS_PER_SEC = %ld, sysconf(_SC_CLK_TCK) = %ld\n", (long)CLOCKS_PER_SEC, sysconf(_SC_CLK_TCK));

	displayProcessTime("start:");
	for (int i = 0; i < 1000000000; ++i)
	{
		getpid();
	}
	printf("\n");
	displayProcessTime("end:");

	return 0;
}

Ссылаться на

[1] WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OFF.COM/MY 3C NOTE / CPP ...

[2] Unix Advanced Environment Programming (третье издание)

[3] Руководство по системному программированию Unix