Chinaunix首页 | 论坛 | 博客
  • 博客访问: 306302
  • 博文数量: 85
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 800
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-18 15:21
文章分类

全部博文(85)

文章存档

2017年(1)

2016年(19)

2015年(55)

2014年(10)

我的朋友

分类: 嵌入式

2015-09-04 22:29:13

在裸机程序,通常可以设定定时器定时Tms来获取准确获取一个时间步子,在不需要精准定时的情况下,可以通过延时或者定时信号触发一个定时。在Linux中如果要获取一个ms级别的定时,该怎么去做实现呢?当然这里要分对时间精准度要求是苛刻的还是说不苛刻的。
1.Linux延时函数usleep sleep nanosleep
参考博文http://blog.csdn.net/lengzijian/article/details/9092367《linux不靠谱的sleep》的测试结果,可知如下表
函数    延时精确度        比较准确的延时范围
usleep    不精确            >=10ms(偏差1.5ms)
sleep     不精确            >=1s(未知ms)
nanosleep 不精确         >=10ms(偏差1.5ms)
select     精确               >=1000us(偏差0.05%~0.1%)

  1. function time(usec) realTime reduce
  2. -------------------------------------------------------------------
  3. /t usleep 500000 501575 1575
  4. /t nanosleep 500000 501861 1861
  5. /t select 500000 499893 -107
  6. /t usleep 100000 101933 1933
  7. /t nanosleep 100000 101957 1957
  8. /t select 100000 99946 -54
  9. /t usleep 50000 51954 1954
  10. /t nanosleep 50000 51962 1962
  11. /t select 50000 49991 -9
  12. /t usleep 10000 11941 1941
  13. /t nanosleep 10000 11973 1973
  14. /t select 10000 9974 -26
  15. /t usleep 1000 2976 1976
  16. /t nanosleep 1000 2974 1974
  17. /t select 1000 993 -7
  18. /t usleep 900 1968 1068
  19. /t nanosleep 900 1978 1078
  20. /t select 900 966 66
  21. /t usleep 500 1971 1471
  22. /t nanosleep 500 1973 1473
  23. /t select 500 992 492
  24. /t usleep 100 1970 1870
  25. /t nanosleep 100 1979 1879
  26. /t select 100 968 868
  27. /t usleep 10 1972 1962
  28. /t nanosleep 10 1974 1964
  29. /t select 10 993 983
  30. /t usleep 1 1969 1968
  31. /t nanosleep 1 1983 1982
  32. /t select 1 960 959
  33. /t usleep 0 988 988
  34. /t nanosleep 0 961 961
  35. /t select 0 5 5
据说usleep还有很大的问题,参见以下地址的博文
/> 2.select函数--select机制
这个机制具有定时唤醒功能,其定时时间从上测试结果可见其是精确的。所以可以用于精确定时。
函数原型见下:
 int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);


   返回:
    >0:就绪描述字的正数目
    0:超时
    -1:出错
首先我们先看一下最后一个参数。它指明我们要等待的时间:

struct timeval{      

        long tv_sec;   /* */

        long tv_usec;  /*微秒 */   

    }


   有三种情况:

    timeout == NULL  等待无限长的时间。等待可以被一个信号中断。当有一个描述符做好准备或者是捕获到一个信号时函数会返回。如果捕获到一个信号, select函数将返回 -1,并将变量 erro设为 EINTR

    timeout->tv_sec == 0 &&timeout->tv_usec == 0不等待,直接返回。加入描述符集的描述符都会被测试,并且返回满足要求的描述符的个数。这种方法通过轮询,无阻塞地获得了多个文件描述符状态。

    timeout->tv_sec !=0 ||timeout->tv_usec!= 0 等待指定的时间。当有描述符符合条件或者超过超时时间的话,函数返回。在超时时间即将用完但又没有描述符合条件的话,返回 0。对于第一种情况,等待也会被信号所中断。
maxfdp1取0
fd_set *readset 取NULL
fd_set *writeset取NULL
fd_set *exceptset取NULL
就可以构造一个由select组成的定时了。
具体例子如下函数形式

void milliseconds_sleep(unsigned long mSec){
    struct timeval tv;
    tv.tv_sec=mSec/1000;
    tv.tv_usec=(mSec%1000)*1000;
    int err;
    do{
       err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);//??这里为什么要加这个errno的判断,EINTR表示信号被中断,什么信号呢?
}
阅读(841) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~