-
2021-05-10 06:23:43
获取当前时间
1. Linux下与时间有关的结构体
struct timeval
{
int tv_sec;
int tv_usec;
};
其中tv_sec是由凌晨开始算起的秒数,tv_usec则是微秒(10E-6 second)。
struct timezone
{
int tv_minuteswest;
int tv_dsttime;
};
tv_minuteswest是格林威治时间往西方的时差,tv_dsttime则是时间的修正方式。
struct timespec
{
long int tv_sec;
long int tv_nsec;
};
tv_nsec是nano second(10E-9 second)。
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;
};
tm_sec表「秒」数,在[0,61]之间,多出来的两秒是用来处理跳秒问题用的。
tm_min表「分」数,在[0,59]之间。
tm_hour表「时」数,在[0,23]之间。
tm_mday表「本月第几日」,在[1,31]之间。
tm_mon表「本年第几月」,在[0,11]之间。
tm_year要加1900表示那一年。
tm_wday表「本第几日」,在[0,6]之间。
tm_yday表「本年第几日」,在[0,365]之间,闰年有366日。
tm_isdst表是否为「日光节约时间」。
struct itimerval
{
struct timeval it_interval;
struct timeval it_value;
};
it_interval成员表示间隔计数器的初始值,而it_value成员表示间隔计数器的当前值。
2.获得当前时间
在所有的UNIX下,都有个time()的函数
time_t time(time_t *t);
这个函数会传回从epoch开始计算起的秒数,如果t是non-null,它将会把时间值填入t中。
对某些需要较高精准度的需求,Linux提供了gettimeofday()。
int gettimeofday(struct timeval * tv,struct timezone *tz);
int settimeofday(const struct timeval * tv,const struct timezone
*tz);
struct tm格式时间函数
struct tm * gmtime(const time_t * t);
转换成格林威治时间。有时称为GMT或UTC。
struct tm * localtime(const time_t *t);
转换成本地时间。它可以透过修改TZ环境变数来在一台机器中,不同使用者表示不同时间。
time_t mktime(struct tm *tp);
转换tm成为time_t格式,使用本地时间。
tme_t timegm(strut tm *tp);
转换tm成为time_t格式,使用UTC时间。
double difftime(time_t t2,time_t t1);
计算秒差。
3.文字时间格式函数
char * asctime(struct tm *tp);
char * ctime(struct tm *tp);
这两个函数都转换时间格式为标准UNIX时间格式。
Mon May 3 08:23:35 1999
ctime一率使用当地时间,asctime则用tm结构内的timezone资讯来表示。
size_t strftime(char *str,size_t max,char *fmt,struct tm
*tp);
strftime有点像sprintf,其格式由fmt来指定。
%a : 本第几天名称,缩写。
%A : 本第几天名称,全称。
%b : 月份名称,缩写。
%B : 月份名称,全称。
%c : 与ctime/asctime格式相同。
%d : 本月第几日名称,由零算起。
%H : 当天第几个小时,24小时制,由零算起。
%I : 当天第几个小时,12小时制,由零算起。
%j : 当年第几天,由零算起。
%m : 当年第几月,由零算起。
%M : 该小时的第几分,由零算起。
%p : AM或PM。
%S : 该分钟的第几秒,由零算起。
%U : 当年第几,由第一个日开始计算。
%W : 当年第几,由第一个一开始计算。
%w : 当第几日,由零算起。
%x : 当地日期。
%X : 当地时间。
%y : 两位数的年份。
%Y : 四位数的年份。
%Z : 时区名称的缩写。
%% : %符号。
char * strptime(char *s,char *fmt,struct tm *tp);
如同scanf一样,解译字串成为tm格式。
%h : 与%b及%B同。
%c : 读取%x及%X格式。
%C : 读取%C格式。
%e : 与%d同。
%D : 读取%m/%d/%y格式。
%k : 与%H同。
%l : 与%I同。
%r : 读取"%I:%M:%S %p"格式。
%R : 读取"%H:%M"格式。
%T : 读取"%H:%M:%S"格式。
%y : 读取两位数年份。
%Y : 读取四位数年份。
下面举一个小例子,说明如何获得系统当前时间:
C代码
time_t now;
struct tm *timenow;
char strtemp[255];
time(&now);
timenow =
localtime(&now);
printf("recent time is : %s /n",
asctime(timenow));
计算时间差 时间间隔
一、用select()函数实现非阻塞时的等待时间,用到结构体struct timeval {},这里就不多说了。
二、用gettimeofday()可获得微妙级(0.000001秒)的系统时间,调用两次gettimeofday(),前后做减法,从而达到定时或者计算时间的目的。
原型:int gettimeofday(struct timeval *tv,struct timezone
*tz),会把目前的时间tv所指的结构返回,当地时区的信息则放到tz所指的结构中。这两个结构都放在/usr/include/sys/time.h
中。
#include
#include
//malloc要用,没有的话,会有警告信息:隐式声明与内建函数'malloc'不兼容。不过警告信息不用管也没事
#include
#include
int main()
{
float time_use=0;
struct timeval start;
struct timeval end;
//struct timezone tz; //后面有说明
gettimeofday(&start,NULL);
//gettimeofday(&start,&tz);结果一样
printf("start.tv_sec:%d\n",start.tv_sec);
printf("start.tv_usec:%d\n",start.tv_usec);
sleep(3);
gettimeofday(&end,NULL);
printf("end.tv_sec:%d\n",end.tv_sec);
printf("end.tv_usec:%d\n",end.tv_usec);
time_use=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);//微秒
printf("time_use is %f\n",time_use);
//输出:time_use is 3001410.000000
//下面的采用指针的方式也可以,但是要注意指针类型若不分配内存的话,编译正确,但是运行结果会不对
}
三、最小到秒的时间的获取
int time(char cnt)
{
time_t t; //实例化time_t结构
struct tm *timenow1; //实例化tm结构指针
struct tm *timenow2;
//实例化tm结构指针
time(&t);//time函数读取现在的时间(国际标准时间非北京时间),然后传值给t
timenow1=localtime(&t);
//localtime函数把从time取得的时间t换算成你电脑中的时间(就是你设置的地区)
printf("the current time1 is:
d:d:d\n",timenow1->tm_hour,timenow1->tm_min,timenow1-
>tm_sec);
printf("Local time1 is %s\n",asctime(timenow1));
//上句中asctime函数把时间转换成字符,通过printf()函数输出
time(&t);
timenow2=localtime(&t);
printf("the current time2 is:
d:d:d\n",timenow2->tm_hour,timenow2->tm_min,timenow1->tm_sec);
printf("Local time2 is %s\n",asctime(timenow2));
if((timenow2->tm_hour==timenow1->tm_hour) &&
(timenow2->tm_min==timenow1->tm_min))
{
n=timenow2->tm_sec-timenow2->tm_sec;
printf("n
is %d\n",n);//秒
}
//注:如果想获得国际标准时间,将localtime换成gmtime函数
//注:time_t是一个在time.h中定义好的结构体。而tm结构体的原形如下:
}
四、纳秒
函数原型:int nanosleep(const struct timespec *rqtp, struct timespec
*rmtp)
其中参数timespec定义是:
struct timespec
{
time_t tv_sec; /* seconds * /
long tv_nsec; /* nanoseconds * /
}
实际应用(部分,不完整):
struct timesepc req;
struct timespec rem;
int ret;
req.tv_sec = 2; //这就表示2秒
req.tv_nsec = 0;
ret = nanosleep(&req, &rem);
if (ret < 0)
{
//....
}
更多相关内容 -
timespec的tv_sec与tv_nsec是否需要相加才是实际消耗时间
2016-01-20 22:33:19如题,我在使用clock_gettime()的过程中发现后一次得到的纳秒数小于前一次得到的纳秒数,是否意味着tv_sec需要与tv_nsec 相加得到的才是实际消耗的时间。 -
Linux C/C++调试之二:使用strace追踪程序系统调用
2019-03-02 18:27:42nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 ...在之前的一篇文章中,我介绍了一种调试手段:利用LD_PRELOAD机制,拦截动态链接器对动态库的符号解析,达到监控程序IO的目的。事实证明我还是太naive了,我们大可利用现成的工具——strace,来更好地完成这一项工作。
strace不只能跟踪程序IO,它能跟踪程序的所有系统调用,实现的基本手段是ptrace系统调用,不过实现细节还没研究过,今天只总结一下它的用法。
首先用strace来跟踪一下喜闻乐见的hello world:
#include <stdio.h> int main() { printf("Hello, world!\n"); return 0; }
$ gcc main.c -o main $ strace ./main
输出是这样的(由于太长,省略了大部分内容):
execve("./main", ["./main"], 0x7ffcea3db620 /* 33 vars */) = 0 ......(太长省略) write(1, "Hello, world!\n", 14Hello, world! ) = 14 exit_group(0) = ? +++ exited with 0 +++
所有系统调用被一一记录了下来,我们可以看出来,printf是通过write系统调用将字符串“Hello, world!\n”写到文件描述符为1的文件(即标准输出)中,从而输出到屏幕上的。
这就是strace最基本的用法,它还提供一些非常实用的参数,我们可以来看一下:
-e
这个参数可以用来过滤输出,它功能很多,具体可以查看strace的手册,我们只用其最基本的功能:跟踪特定的系统调用。
$ strace -e write ./main
输出瞬间清爽了:
write(1, "Hello, world!\n", 14Hello, world! ) = 14 +++ exited with 0 +++
-k
这个参数可以用来输出堆栈,不过strace的帮助将其标记为了实验性功能。
$ strace -e write -k ./main
输出为:
write(1, "Hello, world!\n", 14Hello, world! ) = 14 > /lib/x86_64-linux-gnu/libc-2.27.so(__write+0x14) [0x110154] > /lib/x86_64-linux-gnu/libc-2.27.so(_IO_file_write+0x2d) [0x8b1bd] > /lib/x86_64-linux-gnu/libc-2.27.so(_IO_do_write+0xb1) [0x8cf51] > /lib/x86_64-linux-gnu/libc-2.27.so(_IO_file_overflow+0x103) [0x8d403] > /lib/x86_64-linux-gnu/libc-2.27.so(_IO_puts+0x1a2) [0x80b62] > /home/imred/Documents/Workspace/playground/strace_blog/main(main+0x10) [0x64a] > /lib/x86_64-linux-gnu/libc-2.27.so(__libc_start_main+0xe7) [0x21b97] > /home/imred/Documents/Workspace/playground/strace_blog/main(_start+0x2a) [0x55a] +++ exited with 0 +++
-t/-tt
这组参数可以用来打印时间戳
-y
这个参数可以在打印文件描述符相关参数时同时把文件描述符对应的文件路径打印出来:
$ strace -e write -y ./main
输出为:
write(1</dev/pts/0>, "Hello, world!\n", 14Hello, world! ) = 14 +++ exited with 0 +++
可以看出来当前内容被输出到了序号为0的伪终端。
由于下面的参数与时间统计有关,所以最好调用耗时较长的系统调用来分析其作用,我使用的是usleep函数,它调用了nanosleep系统调用,代码为:
#include <unistd.h> int main() { for (int i = 0; i < 10; i++) { usleep(1000); } return 0; }
-T
这个参数可以用来输出每个系统耗费的时间,这个时间是系统调用开始时间和结束时间之差。
$ strace -e nanosleep -T ./main
输出为:
nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001089> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001078> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001972> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001108> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001139> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001091> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001093> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001326> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001029> nanosleep({tv_sec=0, tv_nsec=1000000}, NULL) = 0 <0.001297> +++ exited with 0 +++
看出来这时间统计的算不上十分准确,最大的误差甚至接近100%,不过这是strace的问题还是系统调用本身的问题并不确定,也还有可能是我使用了虚拟机的缘故。
-c
这个参数用来汇总系统调用的数据。
$ strace -c ./main
输出为:
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 0.00 0.000000 0 1 read 0.00 0.000000 0 2 close 0.00 0.000000 0 8 7 stat 0.00 0.000000 0 2 fstat 0.00 0.000000 0 5 mmap 0.00 0.000000 0 4 mprotect 0.00 0.000000 0 1 munmap 0.00 0.000000 0 1 brk 0.00 0.000000 0 3 3 access 0.00 0.000000 0 10 nanosleep 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 10 8 openat ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000000 49 18 total
能够分析出每种系统调用总的相对时间、总的绝对时间、平均开销、调用次数、出错次数信息。
你可能会比较奇怪为什么上面汇总出来的时间消耗都是0,至少nanosleep该消耗了时间。这是因为在默认情况下统计的都是系统时间,即进程在内核空间执行代码消耗的cpu时间,而不是墙上时间。调用了nanosleep虽然消耗了用户的时间,但并没有占用多少cpu时间,所以统计出来就是0了,如果要统计墙上时间,需要下面的这个选项。
-w
这个参数指定-c参数统计墙上时间。
$ strace -wc ./main
输出为:
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 97.95 0.015065 1507 10 nanosleep 0.64 0.000098 98 1 execve 0.38 0.000058 6 10 8 openat 0.24 0.000037 5 8 7 stat 0.20 0.000031 6 5 mmap 0.18 0.000028 7 4 mprotect 0.11 0.000017 6 3 3 access 0.10 0.000016 16 1 munmap 0.06 0.000009 5 2 fstat 0.05 0.000008 4 2 close 0.03 0.000005 5 1 read 0.03 0.000005 5 1 brk 0.03 0.000004 4 1 arch_prctl ------ ----------- ----------- --------- --------- ---------------- 100.00 0.015381 49 18 total
这回输出结果大致符合我们的预期了(虽然误差很大)。
-f
这个参数指定strace要跟踪从主线程衍生出来的其他线程和进程。
对于下面的程序:
#include <thread> #include <unistd.h> void loopSleep() { for (int i = 0; i < 10; i++) { usleep(1000); } } int main() { std::thread t1([](){ loopSleep(); }); std::thread t2([](){ loopSleep(); }); t1.join(); t2.join(); return 0; }
nanosleep都没有在主线程调用,如果我们直接这样调用strace的话:
$ strace -e nanosleep ./main
其输出为:
+++ exited with 0 +++
并没有追踪到nanosleep的调用。这时就需要指定-f参数了:
$ strace -e nanosleep -f ./main
其输出为:
strace: Process 4623 attached [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, strace: Process 4622 attached <unfinished ...> [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] nanosleep({tv_sec=0, tv_nsec=1000000}, <unfinished ...> [pid 4623] <... nanosleep resumed> NULL) = 0 [pid 4623] +++ exited with 0 +++ [pid 4622] <... nanosleep resumed> NULL) = 0 [pid 4622] +++ exited with 0 +++ +++ exited with 0 +++
追踪到了我们指定的nanosleep系统调用。
-p
这个参数指定strace连接到指定进程上。
以上就是strace这把“锤子”的大致使用手册,但是如何把我们当前遇到的问题归约成“钉子”就没有手册可以参考了,需要各位各显神通了。
-
Linux c运行库中时间的相关函数(三)
2020-01-07 10:25:13printf("CLOCK_PROCESS_CPUTIME_ID: %ld, %ld\n", t.tv_sec, t.tv_nsec); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t); printf("CLOCK_THREAD_CPUTIME_ID: %ld, %ld\n", t.tv_sec, t.tv_nsec); printf("Time ...13. int stime(const time_t *when)
头文件:#include <time.h>
说明:该函数用于设置系统日期和时间,需要root权限,其内部实现是调用settimeofday。
返回值:成功返回0,失败返回-1,错误码存于errno
示例:
#include <time.h> #include <errno.h> #include <stdio.h> int main(int argc, char *argv[]) { int ret = -1; time_t t = 3600*2; time_t now = time(NULL); printf("System old time: %s\n", ctime(&now)); ret = stime(&t); if (ret == 0) { now = time(NULL); printf("System new time: %s\n", ctime(&now)); } else { printf("stime error, code: %d\n", errno); } return 0; }
运行结果:
14. size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *tp)
头文件:#include <time.h>
说明:该函数主要用于格式化时间字符串,它根据format指向的字符串中格式命令把tp中保存的时间信息放在s指向的字符串中,最多向s中存放maxsize个字符。
返回值:返回储存到s的字符数。
示例:
#include <time.h> #include <stdio.h> int main(int argc, char *argv[]) { struct tm *p; char buf[128] = {0}; time_t now = time(NULL); p=localtime(&now); printf("System now time: %s\n", asctime(p)); strftime(buf, sizeof(buf), "Now is: %A %B %d %T %Y\n", p); printf("%s", buf); return 0; }
运行结果:
15. char *strptime(const char *buf, const char *format, struct tm *tm)
头文件:#include <time.h>
说明:该函数用于将特定时间格式字符串转换为tm时间类型。
返回值:成功返回指向此函数调用中未处理的第一个字符的指针,失败返回空指针
示例:
#include <time.h> #include <stdio.h> int main(int argc, char *argv[]) { struct tm timeinfo; char buf[] = "2020-1-6 18:00:00"; char fmt[] = "%Y-%m-%d %H:%M:%S"; if (strptime(buf, fmt, &timeinfo) != NULL) { printf("Format time: %s\n", asctime(&timeinfo)); } return 0; }
运行结果:
16. int clock_gettime(clockid_t clock_id, struct timespec *tp)
头文件:#include <time.h>
说明:该函数可以根据clock_id,获取不同类型的精确时间(纳秒)。clock_id指定需要获取的时钟时间,常用的有4种时间:1)CLOCK_REALTIME,系统实时时间,随系统实时时间改变而改变(从UTC 1970-1-1 0:0:0开始计时);2)CLOCK_MONOTONIC,从系统启动时刻起开始计时,不受系统时间改变的影响,不能被设置;3)CLOCK_PROCESS_CPUTIME_ID,本进程启动后至当前所占用系统处理器的时间;4)CLOCK_THREAD_CPUTIME_ID,本线程启动后至当前所占用系统处理器的时间。
返回值:成功返回0,失败返回-1
示例:
#include <time.h> #include <stdio.h> // 返回自系统开机以来的秒数(tick) unsigned long GetTickCount() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec*1000 + ts.tv_nsec/1000000); } int main(int argc, char *argv[]) { struct timespec t = {0, 0}; clock_gettime(CLOCK_REALTIME, &t); printf("CLOCK_REALTIME: %ld, %ld\n", t.tv_sec, t.tv_nsec); clock_gettime(CLOCK_MONOTONIC, &t); printf("CLOCK_MONOTONIC: %ld, %ld\n", t.tv_sec, t.tv_nsec); clock_gettime(CLOCK_MONOTONIC_RAW, &t); printf("CLOCK_MONOTONIC_RAW: %ld, %ld\n", t.tv_sec, t.tv_nsec); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); printf("CLOCK_PROCESS_CPUTIME_ID: %ld, %ld\n", t.tv_sec, t.tv_nsec); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t); printf("CLOCK_THREAD_CPUTIME_ID: %ld, %ld\n", t.tv_sec, t.tv_nsec); printf("Time now %ld\n", time(NULL)); printf("Tick count %lums\n", GetTickCount()); return 0; }
运行结果:
17. int clock_settime(clockid_t clock_id, const struct timespec *tp)
头文件:#include <time.h>
说明:该函数主要用于设置系统时间,clock_id取值跟clock_gettime相同。
返回值:成功返回0,失败返回-1
示例:
#include <time.h> #include <errno.h> #include <stdio.h> int main(int argc, char *argv[]) { int ret = -1; struct timespec tpset; time_t now = time(NULL); printf("System old time: %s\n", ctime(&now)); tpset.tv_sec = 3600*2; tpset.tv_nsec = 0; ret = clock_settime(CLOCK_REALTIME, &tpset); if (ret == 0) { now = time(NULL); printf("System new time: %s\n", ctime(&now)); } else { printf("clock_settime error, code: %d\n", errno); } }
运行结果:
18. clock_t clock(void)
头文件:#include <time.h>
说明:该函数用于统计某个进程或函数占用处理器的时间。为了获取占用处理器所使用的秒数,需要除以CLOCKS_PER_SEC。不过一般使用gettimeofday替代。
返回值:成功返回自程序启动起,占用处理器时钟所使用的时间,失败返回-1
示例:
#include <time.h> #include <stdio.h> int main(int argc, char *argv[]) { double total = 0; clock_t t1, t2; t1 = clock(); printf("t1=%ld\n", t1); for (int i=0; i< 10000000; i++) { ; } t2 = clock(); printf("t2=%ld\n", t2); total = (double)(t2 - t1)/CLOCKS_PER_SEC; printf("total time:%fs\n", total); return 0; }
运行结果:
19. double difftime(time_t time1, time_t time0)
头文件:#include <time.h>
说明:该函数用于计算time1和time0之间相差的秒数 (time1 - time0)。这两个时间均表示自纪元 Epoch(协调世界时 UTC:1970-01-01 00:00:00)起经过的秒数。
返回值:两个时间之间相差的秒数
示例:
#include <time.h> #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { double diff; time_t start, end; time(&start); printf("start=%ld\n", start); sleep(5); time(&end); printf("end=%ld\n", end); diff = difftime(end, start); printf("Total time consuming=%f\n", diff); return 0; }
运行结果:
-
linux定时器timerfd系列函数学习
2019-04-29 17:09:32new_value.it_value.tv_nsec = now.tv_nsec; if (argc == 2) { new_value.it_interval.tv_sec = 0; max_exp = 1; } else { new_value.it_interval.tv_sec = atoi(argv[2]); max_exp = atoi(argv...使用timerfd的好处是可以结合epoll或poll或select使用,当超时时间到时epoll等会返回可读。
1.
int timerfd_create(int clockid,int flags)
timerfd_create返回一个文件描述符,该文件描述符和定时器所关联。
clockid:
clockid可以为CLOCK_REALTIME或者CLOCK_MONOTONIC。最好使用CLOCK_MONOTONIC,这样的话即使你改变了系统时钟的话也不会受到影响,但是CLOCK_REALTIME会受到硬性。如果对这两个选项感兴趣的话可以自行去网上查写关于他们的资料。
flags:
flags可以是TFD_NONBLOCK、TFD_CLOEXEC的或。设置TFD_NONBLOCK代表把返回的文件描述符设置为非阻塞模式,这个和用fcntl设置该文件描述符的O_NONBLOCK的效果一样。设置TFP_CLOEXEC代表当执行exec时该文件描述符会自动关闭。
2.
int timerfd_settime(int fd,int flags,const struct itimerspec *new_value,struct itimerspec *old_value)
timerfd_settime可以启动或者停止定时器。
让我们先看看两个结构体:
struct timespec{
time_t tv_sec;//秒数
long tv_nsec;//纳秒数
}
struct itimerspec{
struct timespec it_interval;
struct timespec it_value;
}
参数说明:
new_value.it_value:设置初始定时器时间。只要new_value.it_value中的tv_sec和tv_nsec有一个不为0,则启动定时器。把new_value.it_value中的tv_sec和tv_nsec都设为0,则停止定时器。(视flags而定,如果flags是0那么new_value.it_value就是相对值,如果flags是TFD_TIMER_ABSTIME,那么new_value.it_value就是绝对时间)
new_value.it_interval:设置定时时间间隔(定时器可以一直定时)。只要new_value.it_interval中的tv_sec和tv_nsec有一个不为0,那么就会在第一次超时之后把定时时间设为这个值。如果把tv_sec和tv_nsec都设为0,那么定时器只会定时一次,不会重复定时。(new_value.it_interval总是设置为相对时间)
flags:flags参数为0,表示启动相对计时器(new_value.it_value指定相对定时时间), TFD_TIMER_ABSTIME用于启动绝对定时器(当时钟的值达到new_value中指定的值时,定时器将到期)。
old_value.it_value:表示上一次设置的定时器还有多久就到时间了(返回相对时间,不管flags设置成什么)
old_value.it_interval:返回上一次设置的值(总是返回相对时间)
3.
int timerfd_gettime(int fd,struct itimerspec *curr_value);
参数:
curr_value:返回还有多久定时器要到期,以及当前设置的循环定时周期。如果it_value中的中的tv_sec和tv_nsec都为0,那么表示定时器已经停止了。curr_value->it_interval返回当前甚至的循环定时周期,如果it_value中的中的tv_sec和tv_nsec都为0,表示该定时器只定时一次,不会循环定时(it_value和it_interval返回的总是相对值)
4.read的返回值
read(timerfd,buf,sizeof(buf)); buf应该是uint64_t。如果有超时时间发生,则从buf返回超时的次数。
1.如果没有设定O_NONBLOCK,则read阻塞,知道下一次超时时间到来。
2.如果设定了O_NONBLOCK,且没有超时时间发生,则置error为EAGAIN。
3.如果buf的大小小于8个字节,那么read置error为EINVAL。
下面附上一段测试程序:第一个参数为第一次超时什么时候发生,第二个参数为超时间隔设为多少,第三个参数为你想要发生多少次超时时间。程序可以在man timerfd_create的最后面找到。
#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Definition of uint64_t */#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)static void print_elapsed_time(void)
{
static struct timespec start;
struct timespec curr;
static int first_call = 1;
int secs, nsecs;if (first_call) {
first_call = 0;
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
handle_error("clock_gettime");
}if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
handle_error("clock_gettime");secs = curr.tv_sec - start.tv_sec;
nsecs = curr.tv_nsec - start.tv_nsec;
if (nsecs < 0) {
secs--;
nsecs += 1000000000;
}
printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
}int main(int argc, char *argv[])
{
struct itimerspec new_value;
int max_exp, fd;
struct timespec now;
uint64_t exp, tot_exp;
ssize_t s;if ((argc != 2) && (argc != 4)) {
fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
argv[0]);
exit(EXIT_FAILURE);
}if (clock_gettime(CLOCK_REALTIME, &now) == -1)
handle_error("clock_gettime");/* Create a CLOCK_REALTIME absolute timer with initial
expiration and interval as specified in command line */new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
new_value.it_value.tv_nsec = now.tv_nsec;
if (argc == 2) {
new_value.it_interval.tv_sec = 0;
max_exp = 1;
} else {
new_value.it_interval.tv_sec = atoi(argv[2]);
max_exp = atoi(argv[3]);
}
new_value.it_interval.tv_nsec = 20;fd = timerfd_create(CLOCK_REALTIME, 0);
if (fd == -1)
handle_error("timerfd_create");if (timerfd_settime(fd,TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
handle_error("timerfd_settime");
struct itimerspec old_value;
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, &old_value) == -1)
handle_error("timerfd_settime");
print_elapsed_time();
printf("timer started\n");for (tot_exp = 0; tot_exp < max_exp;) {
s = read(fd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");tot_exp += exp;
print_elapsed_time();
printf("read: %llu; total=%llu\n",
(unsigned long long) exp,
(unsigned long long) tot_exp);
}exit(EXIT_SUCCESS);
} -
获取时间戳信息
2022-01-07 13:17:48获取本地时间戳信息 time_t Get_Timestamp(int accuracy = 1) //0:s,1:ms,2:us,3:ns { struct timespec tv; clock_gettime(CLOCK_REALTIME,...return tv.tv_sec * 1000 + tv.tv_nsec / 1000000; case 2: return tv.tv_s -
C代码计时
2021-12-08 17:38:34#include <stdio.h> #include <time.h> static timespec diff(timespec start, timespec end){ timespec temp; if ((end.tv_nsec - start.tv_nsec) &... temp.tv_nsec = 1000000000 + end.tv_nsec - . -
linux下获取当前时间相关函数
2021-06-17 11:11:07linux系统下获取当前时间: 1:可以获取当前时间的s数 结构体: time_t 函数 time_t time(time_t * timer) 2:可以获取到当前时间的微秒数 ...函数: int gettimeofday(struct timeval *tv, struct time... -
Linux下如何使用函数获取ns级时间
2021-05-11 19:36:43printf(“duration:%llus %lluns\n”, time_end.tv_sec-time_start.tv_sec, time_end.tv_nsec-time_start.tv_nsec); return 0; } 编译命令: 代码如下: gcc test.c -o test -lrt 运行结果: 代码如下: 。/... -
时间、定时器与休眠
2021-07-28 23:38:36long tv_nsec //Nanoseconds. }; ③、删除定时器timer_delete() int timer_delete (timer_t timerid); 通过timder id删除指定的 timer 0 - 成功; -1 - 失败,errno被设置。 ④、获取定时器当前值timer_gettime() ... -
linux – 获取一个纳秒精确的atime,mtime,ctime字段的文件(stat?)
2021-05-12 13:58:10Glibc exposes the nanosecond component of each field using names of the form st_atim.tv_nsec if the _BSD_SOURCE or _SVID_SOURCE feature test macro is defined. These fields are specified in POSIX.1-... -
glibc源码分析之stat系列函数
2021-05-13 00:45:12buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec; buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec; buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec; buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec; buf->st_ctim.tv_... -
linux 高精度struct timespec 和 struct timeval
2019-06-20 10:38:33一、struct timespec 定义: typedef long time_t; #ifndef _TIMESPEC #define _TIMESPEC struct timespec { time_t tv_sec;... long tv_nsec; // and nanoseconds }; #endif struct timespe... -
再谈 Linux下的nanosleep函数【转】
2020-05-07 15:07:19这个函数功能是暂停某个进程直到你规定的时间后恢复,参数req就是你要暂停的时间,其中req->tv_sec是以秒为单位,而tv_nsec以纳秒为单位(10的-9次方秒)。由于调用nanosleep是使进程进入TASK_INTERRUPTIBLE,这就... -
Linux高精度struct timespec 和 struct timeval
2021-11-07 22:07:49一、struct timespec 定义: #ifndef _TIMESPEC ... long tv_nsec; // and nanoseconds }; #endif struct timespec有两个成员,一个是秒,一个是纳秒, 所以最高精确度是纳秒。 一般由函数int clock_gettime(c.. -
Linux时钟精度:毫秒?微妙?纳秒?
2021-05-10 21:54:05xtime.tv_nsec以纳秒为单位,记录从上一秒开始经过的纳秒数。就是说,它的精度是纳秒。 C struct timespec xtime; struct timespec{ time_t tv_sec; //秒 long tv_nsec; //纳秒 }; 1 2 3 4 5 6 structtimespecxtime;... -
Linux时间相关知识小结:struct timeval、timespec、gettimeofday、time、localtime....
2022-02-06 22:49:29前言 我们在linux平台进行开发时,时间... __syscall_slong_t tv_nsec; /* Nanoseconds. 纳秒*/ }; 说明 该结构体只是包括秒和纳秒,并没有任何其他含义,比如1970年以来的秒数等。只是个存放空间。为clock_gettime的 -
C语言线程函数
2021-05-23 09:56:18// 秒≥0 long tv_nsec; // 0 ≤纳秒≤999 999 999 结构中成员的顺序未被指定。在下面的例子中,除非通过信号来唤醒,否则正在调用的线程将等待至少 100 毫秒: struct timespec duration = {0}; duration.tv_nsec ... -
XILINX的PCIE实现分析:LINUX下PCIE对应文件的介绍和使用
2021-12-02 06:22:120 <= nsec */ static int timespec_check(struct timespec *t) { if ((t->tv_nsec ) || (t->tv_nsec >= 1000000000)) return -1; return 0; } void timespec_sub(struct timespec *t1, struct timespec *t2) { if ... -
linux用户空间获得ns纳秒级时间示例
2021-03-14 21:20:56printf("duration:%llus %lluns\n", time_end.tv_sec-time_start.tv_sec, time_end.tv_nsec-time_start.tv_nsec); return 0; } 编译命令: gcc test.c -o test -lrt 运行结果: ./test start time 1397395863s,... -
Linux获取系统时间 C++
2019-05-03 14:41:14代码(可以把clock_gettime换成time(NULL)) void getNowTime() { timespec time; clock_gettime(CLOCK_REALTIME, &time); //获取相对于1970到现在的秒数 tm nowTime;...time.tv_sec, &am... -
poll和ppoll学习笔记
2020-11-10 17:45:55/* seconds */ long tv_nsec; /* nanoseconds */ }; 函数原型介绍 poll 依赖头文件 #include 函数定义 int poll(struct pollfd *fds, nfds_t nfds, int timeout); 功能和select相同,同时监听多个fd上的指定事件。... -
C语言跨平台时间操作计算时间差
2021-06-28 20:09:13return timespec_value.tv_sec*1000LL+timespec_value.tv_nsec/1000; #else time_t current_time = time(NULL); return current_time*1000LL; #endif } #endif 计算时间差 #include #include #include"../include/... -
Linux信号实践(5) --时间与定时器
2016-01-02 12:47:51tv_nsec; /* nanoseconds: 纳秒 */ }; 三种时间结构 [cpp] view plain copy time_t [cpp] view plain copy ... -
linux C语言获取时间
2021-05-11 22:30:14printf("duration:%llus %lluns\n", time_end.tv_sec-time_start.tv_sec, time_end.tv_nsec-time_start.tv_nsec); return 0; } #include #include #include int main(){ clock_t start, finish; double duration; ... -
linux定时中断的三种实现
2021-02-04 17:34:58linux下定时中断(信号)的实现方式: 三种定时中断实现: setitimer 函数产生SIGALRM信号,同时使用signal函数注册 ... 使用 timer_create +timer_settime 函数 通知线程 这篇文章写的比较好,可以直接参考: ...... -
SylixOS下移植glib时clock_gettime函数分析
2017-12-02 13:47:14printf("CLOCK_MONOTONIC : %llu \n", tv.tv_sec * 1000 + tv.tv_nsec / 1000000); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tv); printf("CLOCK_PROCESS_CPUTIME_ID : %llu \n", tv.tv_sec * 1000 + tv.tv_... -
选择排序法及时间测试
2016-05-12 14:42:00printf("cost time: %ld ms\n", (ts_end.tv_nsec - ts_start.tv_nsec) / 1000); printf("After sort: \n"); show_array(list, n); printf("how many number do you want to sort(), -1 to quit: \n");... -
Linux上的GetTickCount函数
2019-09-17 20:03:38#include <time.h> // 返回自系统开机以来的毫秒数(tick) unsigned long GetTickCount() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &... return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000...