精华内容
下载资源
问答
  • 2021-11-03 20:38:56
    //1.demo_01.cpp
    #include<iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/time.h>
    #include <unistd.h>
    
    int main(){
    	struct timeval tv;
    	unsigned long  sec_start,sec_end,ms_start,ms_end,us_start,us_end;
    	//start time
    	gettimeofday(&tv,NULL);
    	sec_start = tv.tv_sec; //sec
    	ms_start = tv.tv_sec*1000 + tv.tv_usec/1000; //ms
    	us_start = tv.tv_sec*1000000 + tv.tv_usec; //us
    
    	printf("sleep 2s\n");
    	sleep(2);	
    
    	//end time
    	gettimeofday(&tv,NULL);
    	sec_end = tv.tv_sec; //sec
    	ms_end = tv.tv_sec*1000 + tv.tv_usec/1000; //ms
    	us_end = tv.tv_sec*1000000 + tv.tv_usec; //us
    
    	printf("sec_delta = %ld s\n",sec_end - sec_start);
    	printf("ms_delta = %ld ms\n",ms_end - ms_start);
    	printf("us_delta = %ld us\n",us_end - us_start);
    }
    

    //2.demo_02.cpp
    #include<iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/time.h>
    #include <unistd.h>
    
    struct timeval tv;
    unsigned long us_start,us_end;
    void start_time(){
    	gettimeofday(&tv,NULL);
    	us_start = tv.tv_sec*1000000 + tv.tv_usec; //us	
    }
    
    void end_time(char *func, int line){
    	gettimeofday(&tv,NULL);
    	us_end = tv.tv_sec*1000000 + tv.tv_usec; //us
    	printf("%s, line = %d, us_delta = %ld us \n",func,line,us_end - us_start);
    }
    
    int main(){
    	start_time();
    	sleep(2);
    	end_time("start_preview()", __LINE__);
    }
    

    更多相关内容
  • timestamp是long long类型的,8字节,足够承载最终计算出来的值,所以像是问题出在tm.tv_sec上,但是tm.tv_sec本身输出的值也是正确的~~~ 我猜原因大概是这样的: 1384764980 * 1000的值已经超出32位...

    今天遇到一个和gettimeofday()相关奇怪的问题,问题描述如下。

    有如下代码,在32bit CentOS 6.3平台上编译后运行

    #include <iostream>
    #include <sys/time.h>
    
    using namespace std;
    
    int main(void) {
            std::cout << __WORDSIZE << std::endl;
    
            struct timeval tm;
            gettimeofday(&tm, NULL);
            cout << "tm.tv_sec: " << tm.tv_sec << endl;
            cout << "tm.tv_usec: " << tm.tv_usec << endl;
            long long timestamp = tm.tv_sec * 1000;
            cout << "timestamp: " << timestamp << endl;
    
            return 0;
    }
    运行结果如下。

    32
    tm.tv_sec: 1384764898
    tm.tv_usec: 303888
    timestamp: 1785428688
    这里的32表明是32bit机器。tm.tv_sec 和 tm.tv_usec的值都是正确的,但timestamp值异常,应该是1384764898000,结果像是被截断了,成了1785428688。


    修改第13行代码如下。即,先将tm.tv_sec强制类型转换成long long 类型,然后再做计算。

    #include <iostream>
    #include <sys/time.h>
    
    using namespace std;
    
    int main(void) {
            std::cout << __WORDSIZE << std::endl;
    
            struct timeval tm;
            gettimeofday(&tm, NULL);
            cout << "tm.tv_sec: " << tm.tv_sec << endl;
            cout << "tm.tv_usec: " << tm.tv_usec << endl;
            long long timestamp = (long long)tm.tv_sec * 1000;
            cout << "timestamp: " << timestamp << endl;
    
            return 0;
    }
    这样改过后,结果正确。
    32
    tm.tv_sec: 1384764980
    tm.tv_usec: 331110
    timestamp: 1384764980000

    但是为什么会这样?timestamp是long long类型的,8字节,足够承载最终计算出来的值,所以像是问题出在tm.tv_sec上,但是tm.tv_sec本身输出的值也是正确的~~~


    我猜原因大概是这样的:

    1384764980 * 1000的值已经超出32位有符号int所能表示的最大上限(2 ^ 31 - 1 = 2147483647)了。

    同时,long long timestamp = tm.tv_sec * 1000很可能被编译器先转成了下面的样子(32位系统下,tm.tv_sec的数据类型 time_t 是4字节int)

    int tmp = tm.tv_sec * 1000;

    long long timestamp = tmp;

    在第一步就已经发生溢出了,第二步赋值给long long型变量还是溢出的值!


    下面用一个小例子 t.cpp 来验证上面的猜测。

    int main(void) {
    	int intValue = 2100000000;
    	long long llValue = intValue * 10;
    	return 0;
    }


    通过 g++ -save-temps -S t.cpp 命令得到g++编译 t.cpp 过程中产生的汇编文件 t.s

    基本上就是,用32位的寄存器做乘10的运算,结果也存在32位eax寄存器中(16-21行,这时已经溢出了),然后在赋值给llValue(22-25行)的时候,扩展成64位寄存器(edx, eax)表示



    =======================================

    对 t.cpp 稍作修改如下,即在 intValue 做乘10操作前,强制类型转换成 long long 类型

    int main(void) {
    	int intValue = 2100000000;
    	long long llValue = (long long)intValue * 10;
    	return 0;
    }

    然后,得到新的汇编代码如下

    	.file	"x.cpp"
    	.text
    .globl main
    	.type	main, @function
    main:
    .LFB0:
    	.cfi_startproc
    	.cfi_personality 0x0,__gxx_personality_v0
    	pushl	%ebp
    	.cfi_def_cfa_offset 8
    	.cfi_offset 5, -8
    	movl	%esp, %ebp
    	.cfi_def_cfa_register 5
    	andl	$-8, %esp
    	pushl	%ebx
    	subl	$20, %esp
    	movl	$2100000000, 4(%esp)
    	movl	4(%esp), %eax
    	movl	%eax, %edx
    	sarl	$31, %edx
    	imull	$10, %edx, %ecx
    	imull	$0, %eax, %ebx
    	.cfi_escape 0x10,0x3,0x7,0x75,0x0,0x9,0xf8,0x1a,0x34,0x1c
    	addl	%ebx, %ecx
    	movl	$10, %ebx
    	mull	%ebx
    	addl	%edx, %ecx
    	movl	%ecx, %edx
    	movl	%eax, 8(%esp)
    	movl	%edx, 12(%esp)
    	movl	%eax, 8(%esp)
    	movl	%edx, 12(%esp)
    	movl	$0, %eax
    	addl	$20, %esp
    	popl	%ebx
    	.cfi_restore 3
    	movl	%ebp, %esp
    	.cfi_def_cfa_register 4
    	popl	%ebp
    	.cfi_restore 5
    	.cfi_def_cfa_offset 4
    	ret
    	.cfi_endproc
    .LFE0:
    	.size	main, .-main
    	.ident	"GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
    	.section	.note.GNU-stack,"",@progbits


    大致的意思就是,通过下面两条指令将数字2100000000保存在eax寄存器中:

    movl $2100000000, 4(%esp)

    movl 4(%esp), %eax

    然后通过无符号乘法运算mull对eax做乘10操作,结果的高32位保存在edx中,低32位保存在eax中

    movl $10, %ebx

    mull %ebx ;eax * ebx = edx,eax

    2100000000的符号位通过算术右移31位获取到,然后也乘10,再加到结果的高32位edx寄存器中。

    即,用两个32位寄存器来表示最终的计算结果,于是没有发生溢出!


    前面的猜测基本正确~~~

    展开全文
  • linux 时间与文件实验

    2013-05-10 12:21:13
    tick.it_value.tv_sec = 1; //十秒钟后将启动定时器 tick.it_value.tv_usec = 0; tick.it_i nt erval.tv_sec =1; //定时器启动后,每隔 1 秒将执行相应的函数 tick.it_i nt erval.tv_usec = 0; //setitimer 将触发...
  • fib, c1_real_secs+9-c1_realt.it_value.tv_sec, (999999-c1_realt.it_value.tv_usec)/1000); getitimer(ITIMER_VIRTUAL, &c1_virtt); printf("Child1 Virtual Time = %2ldSec: %03ldMsec\n", c1_virtual_...

    一、引言

    练习编写调用内核的时间测量功能为应用程序测量和精确定时。

    通过这个实验进一步了解Linux内核的定时机制及其数据结构以及怎样从用户空间去访问内核空间的时间数据。

    二、实验内容

    问题A:使用ITIMER_REAL型定时器实现一个gettimeofday(),将它设置为每秒产生一个信号,并计算已经经过的秒数。

    问题B:使用以上实现的gettimeofday()实现一个精确到微秒级的“壁钟”。

    三、实验代码

    /*****************************************
    *
    * 内核的定时机制
    *
    * Copyright: (C) 2018.4.24 by shaomingshan
    *
    * Compile: gcc -g -o main_a main_a.c
    *
    * Execute: ./main_a
    *
    *****************************************/
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/time.h>
    #include <signal.h>
    
    static void sig_real(int);
    static long real_secs = 0;
    static struct itimerval realt;
    
    
    int main(int argc, char *argv[])
    {
        signal(SIGALRM, sig_real);
        realt.it_interval.tv_sec  = 0;
        realt.it_value.tv_sec     = 0;
        realt.it_interval.tv_usec = 999999;
        realt.it_value.tv_usec    = 999999;
        setitimer(ITIMER_REAL, &realt, NULL);
    
        for(;;);
        return 0;
    }
    
    static void sig_real(int non) {
        real_secs += 1;
        printf("%ld\r", real_secs);
        fflush(stdout);
    }
    
    /*****************************************
    *
    * 内核的定时机制
    *
    * Copyright: (C) 2018.4.24 by shaomingshan
    *
    * Compile: gcc -g -o main_b main_b.c
    *
    * Execute: ./main_b
    *
    *****************************************/
    #include <sys/time.h>
    #include <stdio.h>
    #include <signal.h>
    
    static void sighandle(int);
    struct timeval now; 
    int today;
    int main(){
    	struct itimerval v;
    	signal(SIGALRM,sighandle);
    	v.it_interval.tv_sec = 0;
    	v.it_interval.tv_usec = 1;
    	v.it_value.tv_sec = 0;
    	v.it_value.tv_usec = 1;
    	setitimer(ITIMER_REAL, &v, NULL);
    	for(;;);
    }
    static void sighandle(int s){
    	gettimeofday(&now, NULL);
    	today = now.tv_sec%(3600*24);
        printf("%02d:%02d:%02d:%ld\r",today/3600+8,(today%3600)/60,(today%3600)%60,now.tv_usec);
    	fflush(stdout);
    }
    
    /*****************************************
    *
    * 内核的定时机制
    *
    * Copyright: (C) 2018.4.24 by shaomingshan
    *
    * Compile: gcc -g -o main_c main_c.c
    *
    * Execute: ./main_c
    *
    *****************************************/
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <sys/time.h>
    #include <wait.h>
    
    // 父进程定时中断处理
    static void psig_real(int);
    static void psig_virtual(int);
    static void psig_prof(int);
    
    // 子进程1定时中断处理
    static void c1sig_real(int);
    static void c1sig_virtual(int);
    static void c1sig_prof(int);
    
    // 子进程2定时中断处理
    static void c2sig_real(int);
    static void c2sig_virtual(int);
    static void c2sig_prof(int);
    
    long unsigned int fibonnacci(unsigned int n);
    
    static long p_real_secs     = 0, 
                c1_real_secs    = 0, 
                c2_real_secs    = 0,
                p_virtual_secs  = 0,
                c1_virtual_secs = 0,
                c2_virtual_secs = 0,
                p_prof_secs     = 0,
                c1_prof_secs    = 0,
                c2_prof_secs    = 0;
    
    static struct itimerval p_realt, c1_realt, c2_realt;
    static struct itimerval p_virtt, c1_virtt, c2_virtt;
    static struct itimerval p_proft, c1_proft, c2_proft;
    
    int main(int argc, char *argv[])
    {
        long unsigned fib = 0;
        int pid1, pid2;
        unsigned int fibarg;
        int status;
        int i;
        
        if (argc < 3) {
            printf("Usage: testsig arg1 arg2 arg3\n");
            return 1;
        }
    
    
        pid1 = fork();
        if (pid1==0) {
    
            signal(SIGALRM, c1sig_real);
            signal(SIGVTALRM, c1sig_virtual);
            signal(SIGPROF, c1sig_prof);
    
            c1_realt.it_interval.tv_sec = 9;
            c1_realt.it_interval.tv_usec = 999999;
            c1_realt.it_value.tv_sec = 9;
            c1_realt.it_value.tv_usec = 999999;
            setitimer(ITIMER_REAL, &c1_realt, NULL);
    
            c1_virtt.it_interval.tv_sec = 9;
            c1_virtt.it_interval.tv_usec = 999999;
            c1_virtt.it_value.tv_sec = 9;
            c1_virtt.it_value.tv_usec = 999999;
            setitimer(ITIMER_VIRTUAL, &c1_virtt, NULL);
    
            c1_proft.it_interval.tv_sec = 9;
            c1_proft.it_interval.tv_usec = 999999;
            c1_proft.it_value.tv_sec = 9;
            c1_proft.it_value.tv_usec = 999999;
            setitimer(ITIMER_PROF, &c1_proft, NULL);
    
            fib = fibonnacci(atoi(argv[1]));
    
            getitimer(ITIMER_REAL, &c1_realt);
            printf("Child1 fib = %ld\nChild1 Real Time    = %2ldSec: %03ldMsec\n", 
                    fib, c1_real_secs+9-c1_realt.it_value.tv_sec,
                    (999999-c1_realt.it_value.tv_usec)/1000);
    
            getitimer(ITIMER_VIRTUAL, &c1_virtt);
            printf("Child1 Virtual Time = %2ldSec: %03ldMsec\n", 
                    c1_virtual_secs+9-c1_virtt.it_value.tv_sec,
                    (999999-c1_virtt.it_value.tv_usec)/1000);
    
            getitimer(ITIMER_PROF, &c1_proft);
            printf("Child1 Prof Time    = %2ldSec: %03ldMsec\n\n", 
                    c1_prof_secs+9-c1_proft.it_value.tv_sec,
                    (999999-c1_proft.it_value.tv_usec)/1000);
    
        } else if ((pid2=fork())==0) {
    
            signal(SIGALRM, c2sig_real);
            signal(SIGVTALRM, c2sig_virtual);
            signal(SIGPROF, c2sig_prof);
    
            c2_realt.it_interval.tv_sec = 9;
            c2_realt.it_interval.tv_usec = 999999;
            c2_realt.it_value.tv_sec = 9;
            c2_realt.it_value.tv_usec = 999999;
            setitimer(ITIMER_REAL, &c2_realt, NULL);
    
            c2_virtt.it_interval.tv_sec = 9;
            c2_virtt.it_interval.tv_usec = 999999;
            c2_virtt.it_value.tv_sec = 9;
            c2_virtt.it_value.tv_usec = 999999;
            setitimer(ITIMER_VIRTUAL, &c2_virtt, NULL);
    
            c2_proft.it_interval.tv_sec = 9;
            c2_proft.it_interval.tv_usec = 999999;
            c2_proft.it_value.tv_sec = 9;
            c2_proft.it_value.tv_usec = 999999;
            setitimer(ITIMER_PROF, &c2_proft, NULL);
    
            fib = fibonnacci(atoi(argv[2]));
    
            getitimer(ITIMER_REAL, &c2_realt);
            printf("Child2 fib = %ld\nChild2 Real Time    = %2ldSec: %03ldMsec\n", 
                    fib, c2_real_secs+9-c2_realt.it_value.tv_sec,
                    (999999-c2_realt.it_value.tv_usec)/1000);
    
            getitimer(ITIMER_VIRTUAL, &c2_virtt);
            printf("Child2 Virtual Time = %2ldSec: %03ldMsec\n", 
                    c2_virtual_secs+9-c2_virtt.it_value.tv_sec,
                    (999999-c2_virtt.it_value.tv_usec)/1000);
    
            getitimer(ITIMER_PROF, &c2_proft);
            printf("Child2 Prof Time    = %2ldSec: %03ldMsec\n\n", 
                    c2_prof_secs+9-c2_proft.it_value.tv_sec,
                    (999999-c2_proft.it_value.tv_usec)/1000);
        } else {
    
            // 父进程设置3种定时处理入口
            signal(SIGALRM, psig_real);
            signal(SIGVTALRM, psig_virtual);
            signal(SIGPROF, psig_prof);
    
            // 初始化父进程3种时间定时器
            p_realt.it_interval.tv_sec = 9;
            p_realt.it_interval.tv_usec = 999999;
            p_realt.it_value.tv_sec = 9;
            p_realt.it_value.tv_usec = 999999;
            setitimer(ITIMER_REAL, &p_realt, NULL);
    
            p_virtt.it_interval.tv_sec = 9;
            p_virtt.it_interval.tv_usec = 999999;
            p_virtt.it_value.tv_sec = 9;
            p_virtt.it_value.tv_usec = 999999;
            setitimer(ITIMER_VIRTUAL, &p_virtt, NULL);
    
            p_proft.it_interval.tv_sec = 9;
            p_proft.it_interval.tv_usec = 999999;
            p_proft.it_value.tv_sec = 9;
            p_proft.it_value.tv_usec = 999999;
            setitimer(ITIMER_PROF, &p_proft, NULL);
    
            fib = fibonnacci(atoi(argv[3]));
    
            getitimer(ITIMER_REAL, &p_realt);
            printf("Parent fib = %ld\nParent Real Time    = %2ldSec: %03ldMsec\n", 
                    fib, p_real_secs+9-p_realt.it_value.tv_sec,
                    (999999-p_realt.it_value.tv_usec)/1000);
    
            getitimer(ITIMER_VIRTUAL, &p_virtt);
            printf("Parent Virtual Time = %2ldSec: %03ldMsec\n", 
                    p_virtual_secs+9-p_virtt.it_value.tv_sec,
                    (999999-p_virtt.it_value.tv_usec)/1000);
    
            getitimer(ITIMER_PROF, &p_proft);
            printf("Parent Prof Time    = %2ldSec: %03ldMsec\n\n", 
                    p_prof_secs+9-p_proft.it_value.tv_sec,
                    (999999-p_proft.it_value.tv_usec)/1000);
            waitpid(0, &status, 0);
            waitpid(0, &status, 0);
        }
        return 0;
    }
    
    static void psig_real(int non) {
        p_real_secs += 10;
    }
    static void psig_virtual(int non) {
        p_virtual_secs += 10;
    }
    static void psig_prof(int non) {
        p_prof_secs += 10;
    }
    static void c1sig_real(int non) {
        c1_real_secs += 10;
    }
    static void c1sig_virtual(int non) {
        c1_virtual_secs += 10;
    }
    static void c1sig_prof(int non) {
        c1_prof_secs += 10;
    }
    static void c2sig_real(int non) {
        c2_real_secs += 10;
    }
    static void c2sig_virtual(int non) {
        c2_virtual_secs += 10;
    }
    static void c2sig_prof(int non) {
        c2_prof_secs += 10;
    }
    
    long unsigned int fibonnacci(unsigned int n) {
        if (n < 3) return 1;
        return fibonnacci(n-1)+fibonnacci(n-2);
    }
    

    四、运行结果

    如有错误请指正

    展开全文
  • 在设置recvfrom超时的时候,发现结构体timeval中的tv_sec是毫秒 timeval tv; memset((void *)&tv, 0, sizeof(tv)); tv.tv_sec = 5000; tv.tv_usec = 0; 这样是5秒超时,如果设置tv.tv_sec = 5; 发现在不停...
  • 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 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这把“锤子”的大致使用手册,但是如何把我们当前遇到的问题归约成“钉子”就没有手册可以参考了,需要各位各显神通了。

    展开全文
  • //把目前的时间用tv 结构体返回 ntp->ntp_transts.intpart = htonl(tv.tv_sec + JAN_1970); ntp->ntp_transts.fracpart = htonl(USEC2FRAC(tv.tv_usec)); *size = NTP_HLEN; return 0; } 3、接受消息 正常socket...
  • 一. Linux下与时间有关的结构体struct timeval ...其中tv_sec是由凌晨开始算起的秒数,tv_usec则是微秒(10E-6 second)。 struct timezone { int tv_minuteswest; int tv_dsttime; }; tv_minuteswest是格
  • c++ winpcap开发(9)

    2017-07-20 22:53:39
    delay=(header->ts.tv_sec - old_ts->tv_sec) * 1000000 - old_ts->tv_usec + header->ts.tv_usec; /* Get the number of Bits per second */ Bps.QuadPart=(((*(LONGLONG*)(pkt_data + 8)) * 8 * 1000000) / ...
  • return tv.tv_sec*1000000 + tv.tv_usec; } /** * 获取当前系统时间(精度毫秒)tv_usec精确到微秒 * */ static inline int64_t getTimeMs() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec*1000 ...
  • 获取时间戳信息

    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
  • linux下获取当前时间相关函数

    千次阅读 2021-06-17 11:11:07
    linux系统下获取当前时间: 1:可以获取当前时间的s数 结构体: time_t ... time_t tv_sec; // seconds long tv_usec; // microseconds }; 函数: int gettimeofday(struct timeval *tv, struct time...
  • 获取当前的时间的秒数和微秒数...函数说明int gettimeofday (struct timeval * tv, struct timezone * tz)1、返回值:该函数成功时返回0,失败时返回-1 2、参数 struct timeval{ long tv_sec; //秒 long tv_use...
  • __time_t tv_sec; /* Seconds. 秒 */ __syscall_slong_t tv_nsec; /* Nanoseconds. 纳秒*/ }; 说明 该结构体只是包括秒和纳秒,并没有任何其他含义,比如1970年以来的秒数等。只是个存放空间。为clock_gettime的
  • timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus product_%d in %d. buffer: ", timer,id, in+1); //printf("timer = %ld us\n",timer); buff[in] = 1; ...
  • linux获取时间,精确到微秒usec

    千次阅读 2018-08-18 20:21:48
    int gettimeofday(struct timeval *tv, struct timezone *tz); 计算时间间隔,精确到微秒: 1.首先获取任务起始时间值,使用上述接口,也可以封装,并记录到微秒 2.中途执行其他任务 3.再次获取任务结束时间值,...
  • Linux时钟精度:毫秒?微妙?纳秒?

    千次阅读 2016-09-05 12:44:03
     sec = xtime.tv_sec;  usec += (xtime.tv_nsec/1000); //由纳秒转为微妙 }while(read_seqretry(&xtime_lock, seq)) while部分使用了seg锁,只看中间的就好了。加了注释之后就很清晰了。由于...
  • linux 定时器 timefd

    千次阅读 2016-10-26 19:33:58
     new_value.it_value.tv_sec = now.tv_sec+1;//1秒后开始执行  new_value.it_value.tv_nsec = now.tv_nsec;  new_value.it_interval.tv_sec = 1;  new_value.it_interval.tv_nsec = 0;  int fd = ...
  • struct timeval结构体 ...该结构体是Linux系统中定义,struct timeval结构体在time.h中的定义为: ...比如当前我写博文时的tv_sec为1244770435,tv_usec为442388,即当前时间距Epoch时间1244770435秒,44238
  • 以微秒为单位的精确计时 long long L1,L2,L3; timeval tv1;...L1 = tv.tv_sec*1000*1000 + tv.tv_usec;   //执行一些代码,如算法1...   //第二次取时间 gettimeofday(&tv,NU
  •  printf("Time3:%ds---%ldns\n",stCurTime3.tv_sec,stCurTime3.tv_nsec);    return 0; } /*****************************************************************************************************/ ...
  • linux 延时及时间函数总结

    千次阅读 2016-10-18 16:22:09
    一、 基础知识 1、时间类型。Linux下常用的时间类型有4个:time_t,struct timeval,struct timespec,struct tm。 (1)time_t是一个长整型,一般用来表示用1970年以来的秒数。... long tv_
  • 1. Linux下与时间有关的结构体  struct timeval  {  int tv_sec;  int tv_usec;  };  其中tv_sec是由凌晨开始算起的秒数,tv_usec则是微秒(10E-6 second)。  struct timez
  • timeval结构体的应用

    2021-04-14 13:03:38
    = flag) { old_sec_ble = timev.tv_sec; old_sec_focus = timev.tv_sec; } else { if ((timev.tv_sec - old_sec_focus) > 4) { blePaired = true; old_sec_focus = timev.tv_sec; } } } else { if (lastFlag != flag...
  • 获取带毫秒的时间 #include <time.h> #include <sys/time.h> //调用函数时候可以传入字符串进行区别和标记 ... struct timeval tv; struct timezone tz; struct tm *p; gettimeofda...
  • time_sec = time_now.tv_sec; time_mil = time_sec * 1000 + time_now.tv_usec/1000; time_mic = time_now.tv_sec10001000 + time_now.tv_usec; printf(“second %ld\n”,time_sec); printf(“millisecond %ld\n”,...
  • int main(int argc ,char *argv[]) { #include <pcap.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> ... long int tv_sec; // 秒数 long int tv_us...
  • Linux时间子系统之时间的表示

    千次阅读 2020-05-11 14:56:46
    在Linux内核中,为了兼容原有的代码,或者符合某种规范,并且还要满足当前... 所以,这个结构体其实和timespec结构体大同小异,tv_sec存的值是一样的,而只需要将timespec中的tv_nsec除以1000就是timeval中的tv_usec。
  • // 微秒 = 毫秒 * 1000 if(time.tv_usec >= 1000000) // 进位,1000 000 微秒 = 1 秒 { time.tv_sec += time.tv_usec / 1000000; time.tv_usec %= 1000000; } t.tv_sec = time.tv_sec; t.tv_nsec = time....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,964
精华内容 17,985
关键字:

tv_sec

友情链接: primeFactorization.java.zip