精华内容
下载资源
问答
  • 在设置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; 发现在不停...
  • 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位寄存器来表示最终的计算结果,于是没有发生溢出!


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

    展开全文
  • 一、代码 #include #include #include #include #include MODULE_VERSION("1.0.0_0"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("gwy");...#ifndef SLEEP_MILLI_SEC #define SLEEP_MILLI_SEC(nMilliSec) \ do

    一、代码

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/types.h>
    #include <linux/kthread.h>
    #include <linux/err.h>
    
    
    MODULE_VERSION("1.0.0_0");
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("gwy");
    
    
    
    #ifndef SLEEP_MILLI_SEC
    #define SLEEP_MILLI_SEC(nMilliSec) \
        do { \
            long timeout = (nMilliSec) * HZ /1000; \
            while (timeout > 0) \
            { \
                timeout = schedule_timeout(timeout); \
            } \
        }while (0);
    #endif
    
    
    struct task_struct* thread = NULL;
    
    void thread_proc(void* arg)
    {
        struct timespec ts;  
    
        //set_current_state(TASK_UNINTERRUPTIBLE);
        while(!kthread_should_stop())
        {
            ts = current_kernel_time();  
            printk("thread_proc:%s. time:%ld\n", (char*)arg, ts.tv_sec);
            
            SLEEP_MILLI_SEC(1000);
        }
    }
    
    static int init_marker(void)
    {
        int err;
    
        printk("init marker.\n");
    
        thread = kthread_create(thread_proc, "thread arg", "my_thread%d", 0);
        if (IS_ERR(thread))
        {
            err = PTR_ERR(thread);
            printk("kthread_create fail.\n");
            return err;
        }
    
        wake_up_process(thread);
    
        printk("thread create.\n");
    
        return 0;
    }
    
    static void exit_marker(void)
    {
        if (thread)
        {
            kthread_stop(thread);
            thread = NULL;
            printk("thread stop.\n");
        }
    
        printk("exit marker.\n");
    }
    
    
    module_init(init_marker);
    module_exit(exit_marker);
    

    二、输出结果


    三、注意

            1)在调用kthread_stop函数时,线程函数不能已经运行结束。否则,kthread_stop函数会一直进行等待。

            2)线程函数必须能让出CPU,以便能运行其他线程。  同时线程函数也必须能重新被调度运行。

            3)注意线程函数的使用,参见“kthread_create的简单使用”。



    参考资料:

            kthread_create的简单使用:http://blog.csdn.net/newnewman80/article/details/7050090

            kthread_create与kerne_thread的区别:http://blog.sina.com.cn/s/blog_5a1e1b770100jfc0.html

    展开全文
  • 例:计算时间戳 struct timeval t_start; gettimeofday(&t_start, NULL); int64_t ts_now = t_start.tv_...此外会发出32位数据溢出,因为t_start.tv_sec是long型,在32位设备上为4个字节,t_start.tv_sec为1...

    例:计算时间戳

    struct timeval t_start;

    gettimeofday(&t_start, NULL);

    int64_t ts_now = t_start.tv_sec * 1000 + t_start.tv_usec / 1000;

    此外会发出32位数据溢出,因为t_start.tv_sec是long型,在32位设备上为4个字节,t_start.tv_sec为1970年开始的秒数,乘以1000会发生4字节溢出截断,导致获取时间戳异常。需改为:

    ts_now = ((int64_t)t_start.tv_sec) * 1000 + ((int64_t)t_start.tv_usec) / 1000;

    展开全文
  • localtime替换为localtime_s

    千次阅读 2016-08-26 11:19:04
     struct tm *ltime=NULL...time_t local_tv_sec = time(NULL);//定义时间错 //ltime = localtime(&local_tv_sec);//转换,vs2013会报错,说不安全, localtime_s(ltime, &local_tv_sec);//所以用localtime_s替换
    

    struct tm *ltime=NULL;//定义结构体变量

    time_t local_tv_sec = time(NULL);//定义时间错

    //ltime = localtime(&local_tv_sec);//转换,vs2013会报错,说不安全,

    localtime_s(ltime, &local_tv_sec);//所以用localtime_s替换

    展开全文
  • linux 性能测试

    2015-03-19 13:45:09
    #include int tim_subtract(struct timeval *result, struct timeval *x, struct timeval *y) { ...if ( x->tv_sec > y->tv_sec ) ...if ((x->tv_sec==y->tv_sec) && (x->tv_usec>y->tv_us
  • 增加时间戳: #include <...g_debug ("tv.tv_sec:%ld, tv.tv_usec:%ld, millisecond:%ld\n", tv.tv_sec, tv.tv_usec, tv.tv_sec*1000+tv.tv_usec/1000); 增加pid ppid: g_debug ("== test == [%s]_[%d] p
  • printf("now time > %d-%d-%d %d:%d:%d:%d:%d\n",tmptime->tm_year+1900,tmptime->tm_mon+1,tmptime->tm_mday,tmptime->tm_hour,tmptime->tm_min,tmptime->tm_sec,(int)tv.tv_usec/1000,(int)tv.tv_usec%1000);...
  • 时间设置settimeofday

    2020-10-24 09:35:15
    void settimeofday() { struct timeval tv; struct timezone tz; gettimeofday(&... printf("tv_sec:%d,tv_usec:%d.\n",tv.tv_sec,tv.tv_usec); printf("tz_minuteswest:%d,tz_dsttime:%d.\n",tz.tz_m...
  • 时间子系统15_获取系统时间

    千次阅读 2013-11-27 21:51:06
    // 获取系统时间 // 注:将timespec转换为timeval 1.1 void do_gettimeofday(struct timeval *tv) { struct timespec now;... tv->tv_sec = now.tv_sec; tv->tv_usec = now.tv_nsec/1000; } // 获取纳秒级系统时
  • struct timeval tv 存储大小未知

    千次阅读 2018-08-15 15:45:24
    void main() {  struct timeval tv;    gettimeofday( &amp;tv,NULL );   ...sec is %d,usec is %d\n",tv.tv_sec,tv.tv_usec );   } 利用gcc gettimeofday.c -o gettimeofday 编译 提示错误...
  • 这个函数用于设置系统当前时间。 其源码分析如下: SYSCALL_DEFINE1(stime, time_t __user *, tptr... #从user space的buffer中copy要设置的时间到tv.tv_sec中 if (get_user(tv.tv_sec, tptr)) return -EFAULT; ...
  • 1. Linux下与时间有关的结构体 struct timeval ...其中tv_sec是由凌晨开始算起的秒数,tv_usec则是微秒(10E-6 second)。  struct timezone {  int tv_minuteswest;  int tv_dsttime;  };  tv_minute
  • clock_gettime获取时间

    万次阅读 2017-11-04 14:20:41
    linux下clock_getting可以用来获取时间,其中需要用到struct timespec结构体,struct timespec结构体如下: struct timespec { time_t tv_sec; long tv_nsec; } 写个小程序测试一下:
  • 获取高精度时间差

    2014-09-18 17:26:47
    // 用来处理更高精度的时间相减函数. e_time必须大于s_time, 否则结果为负 struct timeval operator-(struct timeval e_time, struct timeval s_time) ...res.tv_sec = e_time.tv_sec - s_time.tv_sec; if (e_tim
  • gettimeofday(struct timeval *tv, struct timezone *tz)函数 功能:获取当前精确时间(Unix时间) ...long tv_sec; // 秒数 long tv_usec; // 微秒数 } timezone为时区 #include #include int main()
  • struct timeval结构体

    2019-11-29 16:54:08
    一、struct timeval结构体 struct timeval结构体在time.h中的定义为: struct timeval { __time_t tv_sec; /* Seconds....__suseconds_t tv_usec;...其中,tv_sec为Epoch到创建struct timeval时的秒数,tv_use...
  • Linux精确计时,及常用C时间函数

    万次阅读 2010-07-16 11:44:00
    L1 = tv.tv_sec*1000*1000 + tv.tv_usec;//执行一些代码,如算法1...//第二次取时间gettimeofday(&tv,NULL);L2 = tv.tv_sec*1000*1000+tv.tv_usec;//执行一些代码,如算法2...gettimeofday(&tv,NULL);L3 = tv.tv_sec*...
  • return : 0:ok ETIMEDOUT: timeout EINVAL: cond ,mutex,abstime invalueble note: struct timeval{ long tv_sec://秒 long tv_used;//微秒 }
  • 一,三种时间结构 time_t://seconds ...long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };   struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */
  • __time_t tv_sec;/*Seconds.*/ __suseconds_t tv_usec;/*Miceoseconds.*/ }; 其中tv_sec是秒数,tv_usec为微秒数. 例如在函数中 struct timeval tv; gettimeofday(&tv, NULL); (*outfile)<<tv.t...
  • #include #define timediff(tv1,tv) (tv1.tv_sec * 1000 * 1000 + tv1.tv_usec - tv.tv_sec * 1000 * 1000 - tv.tv_usec) timeval tv; gettimeofday(&tv,NULL);timeval tv1; gettimeofday(&tv1,NULL); d
  • gettimeofday实现微秒计时

    千次阅读 2017-01-04 10:28:53
    微秒计时实现如下: long time_long=0; double time_double=0; struct timeval tv; gettimeofday(&tv,NULL);... printf("microsecond:%ld\n",tv.tv_sec*1000000 + tv.tv_usec); //微秒 time_long=tv.tv_sec
  • 一些内核定时API (2)

    2018-06-02 09:07:30
    //比较两个时间结构体的大小,前大1,后大-1,return相减是为了保险static inline int timespec_compare(const struct timespec *lhs, ...tv_sec &lt; rhs-&gt;tv_sec) return -1; if (lhs-&gt;tv_sec ...
  • linux微妙和秒定时器

    2017-09-12 17:29:14
    main: struct itimerval t; fflush(stdout); setvbuf(stdout,NULL,_IONBF,0); ...t.it_interval.tv_usec =20000;...t.it_interval.tv_sec = 0; t.it_value.tv_usec =20000; t.it_value.tv_sec = 0; if( setitimer
  • linux c 定时器

    2017-11-09 09:20:49
    struct itimerval t; fflush(stdout); setvbuf(stdout,NULL,_IONBF,0); t.it_interval.tv_usec =20000;... t.it_interval.tv_sec = 0; t.it_value.tv_usec =20000; t.it_value.tv_sec = 0; if( setitimer( ITIME
  • 定时器timer_create timerfd_create

    千次阅读 2019-04-07 10:11:57
    一、相关结构体、数据类型 1. struct timespec struct itimerspec struct timespec { ... time_t tv_sec; /* Seconds */ long tv_nsec; /* Nanoseconds */ }; struct itimerspec { struc...
  • 关于 struct timeval struct timeval { __time_t tv_sec;/*Seconds.*/ ...其中tv_sec是Epoch到创建结构体timeval的秒数,tv_usec为微秒数,也就是秒数后面的零头, 下面做一个实验 #include #inclu
  • void do_gettimeofday(struct timeval *tv) { struct timespec now;...tv->tv_sec = now.tv_sec; tv->tv_usec = now.tv_nsec/1000; } 这里面有个重要的结构体 struct timeval { __kerne

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,759
精华内容 15,903
关键字:

tv_sec