在裸机程序,通常可以设定定时器定时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%)
-
function time(usec) realTime reduce
-
-------------------------------------------------------------------
-
/t usleep 500000 501575 1575
-
/t nanosleep 500000 501861 1861
-
/t select 500000 499893 -107
-
/t usleep 100000 101933 1933
-
/t nanosleep 100000 101957 1957
-
/t select 100000 99946 -54
-
/t usleep 50000 51954 1954
-
/t nanosleep 50000 51962 1962
-
/t select 50000 49991 -9
-
/t usleep 10000 11941 1941
-
/t nanosleep 10000 11973 1973
-
/t select 10000 9974 -26
-
/t usleep 1000 2976 1976
-
/t nanosleep 1000 2974 1974
-
/t select 1000 993 -7
-
/t usleep 900 1968 1068
-
/t nanosleep 900 1978 1078
-
/t select 900 966 66
-
/t usleep 500 1971 1471
-
/t nanosleep 500 1973 1473
-
/t select 500 992 492
-
/t usleep 100 1970 1870
-
/t nanosleep 100 1979 1879
-
/t select 100 968 868
-
/t usleep 10 1972 1962
-
/t nanosleep 10 1974 1964
-
/t select 10 993 983
-
/t usleep 1 1969 1968
-
/t nanosleep 1 1983 1982
-
/t select 1 960 959
-
/t usleep 0 988 988
-
/t nanosleep 0 961 961
-
/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表示信号被中断,什么信号呢?
}
阅读(908) | 评论(0) | 转发(0) |