免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8215 | 回复: 12
打印 上一主题 下一主题

[Linux] Linux用户层定时器,如何解决误差太大的问题,包含setitimer和select的尝试 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-07-30 20:10 |只看该作者 |倒序浏览
在Linux用户层应用编程时,往往会使用到定时器的操作。关于误差太大的问题,还望同志们能给出意见。(内核版本2.6.32)

具体需求是:需要10mS定时器一个,用户层会在定时器服务程序中发送信号量来唤醒其它线程。进程采用SCHED_FIFO。

网上关于定时器的应用主要有两个,select和setitimer,在应用中均有测试,但是误差都比较大,而且不稳定,在ubuntu虚拟机和ARM板上都有测试,大的误差会超过1mS,不满足实际需求。

如果有经验的同志还望不吝分享。

setitimer和select的测试代码网上有很多,基本大同小异,为减小篇幅,就不附完整代码了,如果同志需要查看代码,会在回复中附上。


/* init */

void init_time(void) {
        struct itimerval val;
        init_sigaction();
        val.it_value.tv_sec = 0;
        val.it_value.tv_usec = 10000;
        val.it_interval = val.it_value;
//        setitimer(ITIMER_PROF, &val, NULL );
        gettimeofday(&SndtimeBf,0);
        setitimer(ITIMER_REAL, &val, NULL );
}
void stop_timer(void) {
        struct itimerval val;
        val.it_value.tv_sec = 0;
        val.it_value.tv_usec = 0;
        val.it_interval = val.it_value;
        setitimer(ITIMER_REAL, &val, NULL );
}
int tim_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
int nsec;
if ( x->tv_sec > y->tv_sec )
return   -1;
if ((x->tv_sec==y->tv_sec) && (x->tv_usec>y->tv_usec))
return   -1;
result->tv_sec = ( y->tv_sec-x->tv_sec );
result->tv_usec = ( y->tv_usec-x->tv_usec );
if (result->tv_usec<0)
{
result->tv_sec--;
result->tv_usec+=1000000;
}
return   0;
}

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
2 [报告]
发表于 2013-07-30 20:17 |只看该作者
跑一个死循环线程, pselect大概睡个多少纳秒.

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
3 [报告]
发表于 2013-07-31 10:55 |只看该作者
回复 1# 21dinglei


    试试clock_gettime和timer_create,不管怎么样,具体某个要求的时间精度和内核的设置以及硬件的支持都相关,所以移植的是比较麻烦的。

论坛徽章:
0
4 [报告]
发表于 2013-07-31 14:21 |只看该作者
回复 2# linux_c_py_php
你好,谢谢回复!对于这个问题,不知道如何回复好,暂贴上我的测试结果:



          function  time(usec)    realTime      reduce
-------------------------------------------------------------------
         usleep         500000     500224        224
         nanosleep      500000     501369       1369
         select         500000     501510       1510
         usleep         100000     100517        517
         nanosleep      100000     100197        197
         select         100000     100940        940
         usleep          50000      50229        229
         nanosleep       50000      50239        239
         select          50000      50721        721
         usleep          10000      10204        204
         nanosleep       10000      10195        195
         select          10000      10235        235
         usleep           1000       1181        181
         nanosleep        1000       1283        283
         select           1000       1593        593
         usleep            900       1191        291
         nanosleep         900       3167       2267
         select            900       1106        206
         usleep            500       1289        789
         nanosleep         500        696        196
         select            500        723        223
         usleep            100        475        375
         nanosleep         100        269        169
         select            100        268        168
         usleep             10        593        583
         nanosleep          10        288        278
         select             10        287        277
         usleep              1        251        250
         nanosleep           1        250        249
         select              1        540        539

论坛徽章:
0
5 [报告]
发表于 2013-07-31 14:26 |只看该作者
回复 3# myworkstation

你好,谢谢回复!所建议的方法已经有过尝试,误差仍是不能满足要求,在PC端的ubuntu上测试效果也是一样的,对于这种情况真是不能接受,如果误差能稳定到1mS以内也是可以的,但是,在测试过程中发现,每次测试的解决并不一致,有的结果会出乎意料,比如:定时10MS,有时会出现误差3MS左右。(对于内核的设置Hz = 1000,对于PC端的bogomips        : 4593.35  ;ARM开发板的bogomips为900多。)


   

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
6 [报告]
发表于 2013-07-31 16:22 |只看该作者
回复 5# 21dinglei
你需要的定时器精度太高了。Linux内核如果不做修改不可能满足你的需求。抢占式内核肯定会存在计时误差。你可以找找RT版本的内核试试。

论坛徽章:
7
天蝎座
日期:2013-09-28 10:45:42双子座
日期:2013-10-16 16:27:09射手座
日期:2013-10-23 10:21:32处女座
日期:2014-09-17 16:44:332015年亚洲杯之巴林
日期:2015-04-09 17:28:01冥斗士
日期:2015-11-26 16:19:0015-16赛季CBA联赛之山东
日期:2018-03-02 23:59:31
7 [报告]
发表于 2013-07-31 17:47 |只看该作者
本帖最后由 cxytz01 于 2013-07-31 17:52 编辑

楼主看看这篇帖子以及man或许有帮助。
我之前遇到过sleep 200ms的,结果概率性出现1~6s线程不执行,不是死锁,后来不了了之。但是换了新型板子之后,再也没出现过。这个问题取决于Hardware Clock,不是software clock决定得了的,应用层定时器总会出现一段jiffy延时。当然还有内核,得看看内核支持的精度。

http://stackoverflow.com/questio ... leep-on-cent-os-6-3

man 7 time
Real time and process time
       Real  time  is  defined  as time measured from some fixed point, either from a standard point in the past (see the description of the Epoch and
       calendar time below), or from some point (e.g., the start) in the life of a process (elapsed time).

       Process time is defined as the amount of CPU time used by a process.  This is sometimes divided into user and system components.  User CPU time
       is  the time spent executing code in user mode.  System CPU time is the time spent by the kernel executing in system mode on behalf of the pro-
       cess (e.g., executing system calls).  The time(1) command can be used to determine the amount of CPU time consumed during the  execution  of  a
       program.  A program can determine the amount of CPU time it has consumed using times(2), getrusage(2), or clock(3).

   The Hardware Clock
       Most computers have a (battery-powered) hardware clock which the kernel reads at boot time in order to initialize the software clock.  For fur-
       ther details, see rtc(4) and hwclock(.

   The Software Clock, HZ, and Jiffies
       The accuracy of many system calls and timestamps is limited by the resolution of the software clock, a clock maintained  by  the  kernel  which
       measures time in jiffies.  The size of a jiffy is determined by the value of the kernel constant HZ.  The value of HZ varies across kernel ver-
       sions and hardware platforms.  On x86 the situation is as follows: on kernels up to and including 2.4.x, HZ was 100, giving a  jiffy  value  of
       0.01  seconds;  starting with 2.6.0, HZ was raised to 1000, giving a jiffy of 0.001 seconds; since kernel 2.6.13, the HZ value is a kernel con-
       figuration parameter and can be 100, 250 (the default) or 1000, yielding a jiffies value of, respectively, 0.01, 0.004, or 0.001 seconds.

论坛徽章:
0
8 [报告]
发表于 2013-08-01 09:38 |只看该作者
回复 6# myworkstation

谢谢回复!更改内核这一方面有过考虑,只是担心改动太大,之前已经基于当前内核做了相关的很多驱动的开发,修改成RTLinux可能改动太大,所以顾忌太多。也考虑过打实时补丁,但是在网上找到的相关的补丁版本与现有内核版本不太符合(2.6.32),同志是否有相关的链接可供分享?

修改内核也是最终不可行后的唯一路径,现仍想通过各种方式来修改当前版本,如果有什么经验想法可否分享。

   

论坛徽章:
0
9 [报告]
发表于 2013-08-01 10:39 |只看该作者
回复 7# cxytz01

你好!谢谢回复!对于我所使用的平台的config_HZ=1000,hrtimer也是打开的CONFIG_HIGH_RES_TIMERS=y;硬件上的晶体是26MHZ的,CPU主频1GHz,这样的参数如果是硬件误差,最终的误差比例也不会出现定时10mS而出现2mS的误差。在测试的时候在ubuntu虚拟机和ARM板都是有测试的,效果都不是很好,虚拟机的HZ之前没有注意,经你提醒,查看了一下,确实是太小(250),那么,ubuntu的Hz该如何更改?直接修改/boot/config-2.6.32-24-generic貌似并不是可行的?
从这些配置看,同志有没有建议给出?


   

论坛徽章:
7
天蝎座
日期:2013-09-28 10:45:42双子座
日期:2013-10-16 16:27:09射手座
日期:2013-10-23 10:21:32处女座
日期:2014-09-17 16:44:332015年亚洲杯之巴林
日期:2015-04-09 17:28:01冥斗士
日期:2015-11-26 16:19:0015-16赛季CBA联赛之山东
日期:2018-03-02 23:59:31
10 [报告]
发表于 2013-08-01 11:23 |只看该作者
回复 9# 21dinglei

内核方面的东西我不会。


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP