免费注册 查看新帖 |

Chinaunix

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

[C++] 高精度的SLEEP [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-05-31 11:40 |只看该作者 |倒序浏览
在hp unix环境下,需要做一个 micro seconds级别的sleep , 以便均匀的报送数据,但是 使用了

usleep,测试 usleep(1),大概就会20ms,
select,稍微好点,tv_usec设置成1时,大概会10ms,

此外也使用过nanosleep,pselect 等等, 都感觉效果不理想.有什么精度更高的办法吗?

论坛徽章:
0
2 [报告]
发表于 2010-05-31 11:43 |只看该作者
人气不旺啊 坐等高手....

论坛徽章:
0
3 [报告]
发表于 2010-05-31 11:49 |只看该作者
没有人做过类似的东西吗?

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
4 [报告]
发表于 2010-05-31 11:57 |只看该作者
这种情况不能用sleep/select系的函数,因为它们会导致程序挂起,主动让出时间片给另外的进程。

后果就是哪怕usleep(1),也必须等到下一次得到时间片时才能继续运行——usleep仅仅是等待的资源可以在1微秒内得到满足而已,程序挂起、等待下一时间片还是必须的。


可行的解决方案大概有两种:
一是忙等,弄个循环,反复取CPU周期数(有类似函数/汇编指令)计算时间。这个方案精确度能达到纳秒级。

二是使用时钟中断。
在X86体系下,标准时钟中断好像是每秒18.2次(这个数据是我脑子的印象,很可能是错的);但可以通过向时钟控制芯片写入数据来改变这个中断的触发频率,并在自己的时钟中断里发送数据(请注意保留旧中断处理逻辑,并仍然按照每秒18.2次的频率调用它)。
可以参考 加速齿轮 之类软件的设计——这是我所知道的唯一相关中文资料,但是windows平台下的。linux/unix体系下可能会有更好的支持方案。


方案1实现简单,但效率较低,且在正常时间片切换时会导致短时间断流;方案2效率高且稳定,但实现难度稍大。

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:50:28
5 [报告]
发表于 2010-05-31 11:59 |只看该作者
用clock_gettime

论坛徽章:
0
6 [报告]
发表于 2010-05-31 12:34 |只看该作者
回复 4# shan_ghost


    方案1我试过了,就是在while里面不断的去gettimeofday,然后求差,结果还算差强人意,但是带来一个问题就是cpu会被弄得很高,占到90%以上.方案2暂时还没有想到怎么实现.非常感谢 !

论坛徽章:
0
7 [报告]
发表于 2010-05-31 13:26 |只看该作者
回复 5# noword2k


    clock_gettime 和楼上 的方案1 是一个原理

论坛徽章:
0
8 [报告]
发表于 2010-05-31 13:27 |只看该作者
setitimer,poll

论坛徽章:
0
9 [报告]
发表于 2010-05-31 13:51 |只看该作者
本帖最后由 wwdwwd 于 2010-05-31 13:52 编辑

最近好多人需要精确时间啊,正好我最近也在弄这个,经测试:settimer和rtc都可以达到要求,不过pc机上rtc只允许一个进程使用。
不过这个是linux下的,hp unix下不知道有没有。
  1. #include <sys/time.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <signal.h>
  5. #include <string.h>

  6. static char msg[] = "time is running out\n";
  7. static int len;

  8. // 向标准错误输出信息,告诉用户时间到了
  9. void prompt_info(int signo)
  10. {
  11.     write(STDERR_FILENO, msg, len);   
  12. }

  13. // 建立信号处理机制
  14. void init_sigaction(void)
  15. {
  16.     struct sigaction tact;
  17.    
  18.     /*信号到了要执行的任务处理函数为prompt_info*/
  19.     tact.sa_handler = prompt_info;
  20.     tact.sa_flags = 0;
  21.     /*初始化信号集*/
  22.     sigemptyset(&tact.sa_mask);
  23.     /*建立信号处理机制*/
  24.     sigaction(SIGALRM, &tact, NULL);
  25. }

  26. void init_time()
  27. {
  28.     struct itimerval value;
  29.    
  30.     /*设定执行任务的时间间隔为0秒1微秒*/
  31.     value.it_value.tv_sec = 0;
  32.     value.it_value.tv_usec = 1;
  33.     /*设定初始时间计数也为0秒1微秒*/
  34.     value.it_interval = value.it_value;
  35.     /*设置计时器ITIMER_REAL*/
  36.     setitimer(ITIMER_REAL, &value, NULL);
  37. }

  38. int main()
  39. {
  40.     len = strlen(msg);
  41.     init_sigaction();
  42.     init_time();
  43.     while ( 1 );
  44.     exit(0);
  45. }
复制代码

论坛徽章:
0
10 [报告]
发表于 2010-05-31 14:04 |只看该作者
回复 9# wwdwwd


    你这段代码我试了一下在我机器上执行时间间隔大概也是20ms...杯具
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP