Linux系統(tǒng)中時(shí)間的獲取和使用
Linux系統(tǒng)時(shí)間有兩種。
(1)日歷時(shí)間。該值是自協(xié)調(diào)世界時(shí)(UTC)1970年1月1日00:00:00這個(gè)特定時(shí)間以來所經(jīng)過的秒數(shù)累計(jì)值?;緮?shù)據(jù)類型用time_t保存。最后通過轉(zhuǎn)換才能得到我們平時(shí)所看到的24小時(shí)制或者12小時(shí)間制的時(shí)間。
(2)進(jìn)程時(shí)間。也被稱為CPU時(shí)間,用以度量進(jìn)程使用的中央處理器資源。進(jìn)程時(shí)間以時(shí)鐘滴答計(jì)算。
本文將給大家詳細(xì)介紹關(guān)于Linux時(shí)間的獲取和使用,下面話不多說了,來一起看看詳細(xì)的介紹吧
獲取時(shí)間戳
time()
#include <time.h> time_t time(time_t *calptr)
- time返回當(dāng)前時(shí)間的時(shí)間戳,也就是從世界時(shí)到現(xiàn)在的秒數(shù);
- time_t實(shí)際就是一個(gè)uint64_t;
- calptr不為空時(shí),時(shí)間戳也會(huì)寫入到該指針中;
調(diào)用示例:
#include <time.h> #include <iostream> #include <stdlib.h> using namespace std; int main() { time_t curTime; curTime = time(NULL); cout << curTime << endl; return 0; }
結(jié)果:
返回一串?dāng)?shù)值,如1533287924
gettimeofday()和clock_gettime()
time函數(shù)只能得到秒精度的時(shí)間,為了獲得更高精度的時(shí)間戳,需要其他函數(shù)。gettimeofday函數(shù)可以獲得微秒精度的時(shí)間戳,用結(jié)構(gòu)體timeval來保存;clock_gettime函數(shù)可以獲得納秒精度的時(shí)間戳,用結(jié)構(gòu)體timespec來保存。
#include <sys/time.h> int gettimeofday(struct timeval *tp, void *tzp); 因?yàn)闅v史原因tzp的唯一合法值是NULL,因此調(diào)用時(shí)寫入NULL即可。 int clock_gettime(clockid_t clock_id, strcut timespec *tsp); clock_id有多個(gè)選擇,當(dāng)選擇為CLOCK_REALTIME時(shí)與time的功能相似,但是時(shí)間精度更高。
兩個(gè)函數(shù)使用的結(jié)構(gòu)體定義如下:
struct timeval { long tv_sec; /*秒*/ long tv_usec; /*微秒*/ }; struct timespec { time_t tv_sec; //秒 long tv_nsec; //納秒 };
調(diào)用示例:
#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; }
結(jié)果:
編譯時(shí)要在編譯命令最后加上-lrt鏈接Real Time動(dòng)態(tài)庫,如
g++ -o time2 test_time_linux_2.cpp -lrtTime1: 1533289490s
Time2: 1533289490s, 133547us
Time3: 1533289490s, 133550060ns
可視化時(shí)間
tm結(jié)構(gòu)體
得到的時(shí)間戳不能直觀的展示現(xiàn)在的時(shí)間,為此需要使用tm結(jié)構(gòu)體來表示成我們?nèi)粘K姷臅r(shí)間,該結(jié)構(gòu)體定義如下:
struct tm { int tm_sec; /*秒,正常范圍0-59, 但允許至61*/ int tm_min; /*分鐘,0-59*/ int tm_hour; /*小時(shí), 0-23*/ int tm_mday; /*日,即一個(gè)月中的第幾天,1-31*/ int tm_mon; /*月, 從一月算起,0-11*/ 1+p->tm_mon; int tm_year; /*年, 從1900至今已經(jīng)多少年*/ 1900+ p->tm_year; int tm_wday; /*星期,一周中的第幾天, 從星期日算起,0-6*/ int tm_yday; /*從今年1月1日到目前的天數(shù),范圍0-365*/ int tm_isdst; /*日光節(jié)約時(shí)間的旗標(biāo)*/ };
time_t轉(zhuǎn)成tm
gmtime 和localtime可以將time_t類型的時(shí)間戳轉(zhuǎn)為tm結(jié)構(gòu)體,用法如下:
struct tm* gmtime(const time_t *timep); //將time_t表示的時(shí)間轉(zhuǎn)換為沒有經(jīng)過時(shí)區(qū)轉(zhuǎn)換的UTC時(shí)間,是一個(gè)struct tm結(jié)構(gòu)指針 stuct tm* localtime(const time_t *timep); //和gmtime功能類似,但是它是經(jīng)過時(shí)區(qū)轉(zhuǎn)換的時(shí)間,也就是可以轉(zhuǎn)化為北京時(shí)間。
固定格式打印時(shí)間
得到tm結(jié)構(gòu)體后,可以將其轉(zhuǎn)為字符串格式的日常使用的時(shí)間,或者直接從time_t進(jìn)行轉(zhuǎn)換,分別可以使用以下兩個(gè)函數(shù)達(dá)到目的。不過這兩個(gè)函數(shù)只能打印固定格式的時(shí)間。
//這兩個(gè)函數(shù)已經(jīng)被標(biāo)記為棄用,盡量使用后面將要介紹的函數(shù) char *asctime(const struct tm* timeptr); char *ctime(const time_t *timep);
調(diào)用示例:
#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; }
結(jié)果:
Fri Aug 3 18:24:29 2018
Fri Aug 3 18:24:29 2018
靈活安全的時(shí)間轉(zhuǎn)換函數(shù)strftime()
上述兩個(gè)函數(shù)因?yàn)榭赡艹霈F(xiàn)緩沖區(qū)溢出的問題而被標(biāo)記為棄用,因此更加安全的方法是采用strftime方法。
/* ** @buf:存儲(chǔ)輸出的時(shí)間 ** @maxsize:緩存區(qū)的最大字節(jié)長度 ** @format:指定輸出時(shí)間的格式 ** @tmptr:指向結(jié)構(gòu)體tm的指針 */ size_t strftime(char* buf, size_t maxsize, const char *format, const struct tm *tmptr);
我們可以根據(jù)format指向字符串中格式,將timeptr中存儲(chǔ)的時(shí)間信息按照format指定的形式輸出到buf中,最多向緩沖區(qū)buf中存放maxsize個(gè)字符。該函數(shù)返回向buf指向的字符串中放置的字符數(shù)。
函數(shù)strftime()的操作有些類似于sprintf():識(shí)別以百分號(hào)(%)開始的格式命令集合,格式化輸出結(jié)果放在一個(gè)字符串中。格式化命令說明串 strDest中各種日期和時(shí)間信息的確切表示方法。格式串中的其他字符原樣放進(jìn)串中。格式命令列在下面,它們是區(qū)分大小寫的。
%a 星期幾的簡寫
%A 星期幾的全稱
%b 月分的簡寫
%B 月份的全稱
%c 標(biāo)準(zhǔn)的日期的時(shí)間串
%C 年份的后兩位數(shù)字
%d 十進(jìn)制表示的每月的第幾天
%D 月/天/年
%e 在兩字符域中,十進(jìn)制表示的每月的第幾天
%F 年-月-日
%g 年份的后兩位數(shù)字,使用基于周的年
%G 年分,使用基于周的年
%h 簡寫的月份名
%H 24小時(shí)制的小時(shí)
%I 12小時(shí)制的小時(shí)
%j 十進(jìn)制表示的每年的第幾天
%m 十進(jìn)制表示的月份
%M 十時(shí)制表示的分鐘數(shù)
%n 新行符
%p 本地的AM或PM的等價(jià)顯示
%r 12小時(shí)的時(shí)間
%R 顯示小時(shí)和分鐘:hh:mm
%S 十進(jìn)制的秒數(shù)
%t 水平制表符
%T 顯示時(shí)分秒:hh:mm:ss
%u 每周的第幾天,星期一為第一天 (值從0到6,星期一為0)
%U 第年的第幾周,把星期日做為第一天(值從0到53)
%V 每年的第幾周,使用基于周的年
%w 十進(jìn)制表示的星期幾(值從0到6,星期天為0)
%W 每年的第幾周,把星期一做為第一天(值從0到53)
%x 標(biāo)準(zhǔn)的日期串
%X 標(biāo)準(zhǔn)的時(shí)間串
%y 不帶世紀(jì)的十進(jìn)制年份(值從0到99)
%Y 帶世紀(jì)部分的十制年份
%z,%Z 時(shí)區(qū)名稱,如果不能得到時(shí)區(qū)名稱則返回空字符。
%% 百分號(hào)
調(diào)用示例:
#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; }
結(jié)果:
time: 08:18:12 PM, Fri Aug 03, 2018
時(shí)間函數(shù)之間的關(guān)系圖
進(jìn)程時(shí)間
進(jìn)程時(shí)間是進(jìn)程被創(chuàng)建后使用CPU的時(shí)間 ,進(jìn)程時(shí)間被分為以下兩個(gè)部分:
- 用戶CPU時(shí)間:在用戶態(tài)模式下使用CPU的時(shí)間
- 內(nèi)核CPU時(shí)間:在內(nèi)核態(tài)模式下使用CPU的時(shí)間。這是執(zhí)行內(nèi)核調(diào)用或其他特殊任務(wù)所需要的時(shí)間。
clock函數(shù)
clock函數(shù)提供了一個(gè)簡單的接口用于取得進(jìn)程時(shí)間,它返回一個(gè)值描述進(jìn)程使用的總的CPU時(shí)間(包括用戶時(shí)間和內(nèi)核時(shí)間),該函數(shù)定義如下:
#include <time.h> clock_t clock(void) //if error, return -1
clock函數(shù)返回值得計(jì)量單位是CLOCKS_PER_SEC,將返回值除以這個(gè)計(jì)量單位就得到了進(jìn)程時(shí)間的秒數(shù)
times函數(shù)
times函數(shù)也是一個(gè)進(jìn)程時(shí)間函數(shù),有更加具體的進(jìn)程時(shí)間表示,函數(shù)定義如下:
#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; };
times函數(shù)雖然返回類型還是clock_t,但是與clock函數(shù)返回值的計(jì)量單位不同。times函數(shù)的返回值得計(jì)量單位要通過sysconf(SC_CLK_TCK)來獲得。
Linux系統(tǒng)編程手冊(cè)上一個(gè)完整的使用案例如下:
#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] http://www.runoob.com/w3cnote/cpp-time_t.html
[2] Unix高級(jí)環(huán)境編程(第三版)
[3] Unix系統(tǒng)編程手冊(cè)
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
如何禁止網(wǎng)站內(nèi)容被搜索引擎收錄的幾種方法講解
今天小編就為大家分享一篇關(guān)于如何禁止網(wǎng)站內(nèi)容被搜索引擎收錄的幾種方法講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03Linux系統(tǒng)rsyslogd占用內(nèi)存過高的問題排查及解決
syslogd不僅僅是記錄kernel log的服務(wù),還能記錄user space中的日志,syslogd是Linux下的一個(gè)記錄日志文件服務(wù),新版本叫做rsyslogd,本文介紹了Linux系統(tǒng)rsyslogd占用內(nèi)存過高的問題排查及解決,需要的朋友可以參考下2024-08-08centos系統(tǒng)搭建本地yum服務(wù)器的方法
YUM是Yellow dog Updater, Modified的縮寫,是由Duke University所發(fā)起的計(jì)劃,目的就是為了解決RPM的依賴關(guān)系的問題,方便使用者進(jìn)行軟件的安裝、升級(jí)等等工作。這篇文章主要給大家介紹了在centos系統(tǒng)搭建本地yum服務(wù)器的方法,有需要的朋友們可以參考借鑒。2016-12-12Ubuntu20的tzselect設(shè)置時(shí)間失效的問題,樹莓派服務(wù)器(推薦)
這篇文章主要介紹了Ubuntu20的tzselect設(shè)置時(shí)間失效的問題,樹莓派服務(wù)器,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05ubuntu開啟SSH服務(wù)遠(yuǎn)程登錄操作的實(shí)現(xiàn)
這篇文章主要介紹了ubuntu開啟SSH服務(wù)遠(yuǎn)程登錄操作的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08用DNSPod和Squid打造自己的CDN (五) 安裝Squid的前期準(zhǔn)備
從本章開始,大家將會(huì)學(xué)到如何在Linux下面安裝、編譯程序,還會(huì)學(xué)到程序編譯的優(yōu)化方法,最后會(huì)通過源代碼編譯的方式把Squid安裝上2013-04-04Linux 詳解 /var/log/xferlog的各個(gè)字段解析
這篇文章主要介紹了Linux 詳解 /var/log/xferlog的各個(gè)字段解析的相關(guān)資料,需要的朋友可以參考下2017-05-05