#include #include#include#include //gettimeofday sleep usleep
#include //open
#include //open
#include //open
#include //error
#include //close
#include //rtc_commadn RTC_IRQP_SET / RTC_PIE_ON / RTC_PIE_OFF
#include //ioctl/**g++ -o timer_test time_test.cc*/
/*定义log输出宏*/
#define DEB_LOG(fmat,...) printf("%s:%d_%s() "fmat"
", __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__)/*设定时钟频率,频率可用范围是2~8192,一定要是2的n次方,8192时,一次约122微妙,*/
#define FREQ 8192
#define USEC_PER_SECOND 1000000
/*根据输入的等待待时间(毫秒),计算循环次数*/
#define CALC_CNT(millseconds) (millseconds * 1000.0 / USEC_PER_SECOND * FREQ + 0.5)
structtimeval tvs, tve;void showTime(int startStop, long sleepT, const char*msg) {if (1 ==startStop) {
gettimeofday(&tvs, 0); //记录定时器开始时间
} else{
gettimeofday(&tve, 0); //记录定时器结束时间
DEB_LOG("%s: [%ldus] [%ldus]", msg, sleepT,
(tve.tv_sec- tvs.tv_sec) *1000000LL+ (tve.tv_usec -tvs.tv_usec));
}
}/** 打开RTC时钟设备
* freq: RTC 时钟的频率
* fd: 读取RTC时钟的fd **/
int openRTC(int freq, int*fd) {/*打开 RTC 时间设备*/
*fd = open("/dev/rtc", O_RDONLY);if (*fd < 0) {
DEB_LOG("open /dev/rtc NG, errno=%d msg=%s", errno, strerror(errno));return -1;
}/*设定 RTC 的时钟频率 2~8192Hz,最小精度为123微秒*/
if (ioctl(*fd, RTC_IRQP_SET, freq) < 0) {
DEB_LOG("ioctl(RTC_IRQP_SET)");
close(*fd);return -1;
}/*启动 RTC 时钟*/
if (ioctl(*fd, RTC_PIE_ON, 0) < 0) {
DEB_LOG("ioctl(RTC_PIE_ON)");
close(*fd);return -1;
}return 0;
}/** 关闭RTC时钟设备
* fd: 读取RTC时钟的fd **/
void closeRTC(intfd) {/*关闭 RTC 时钟计时*/ioctl(fd, RTC_PIE_OFF,0);/*关闭 RTC 装置*/close(fd);
}/*使用ioctl的情况下的,计时器函数*/
int rtcTimer(int millseconds, intfd) {int loopNum =CALC_CNT(millseconds);
unsignedlong data = 0;for (int i = 0; i < loopNum; i++) {/*read一次的时间 = 1秒/时钟频率 (频率范围 2~8192,最小精度为123微秒)*/
if (read(fd, &data, sizeof(unsigned long)) < 0) {return -1;
}
}return 0;
}int main(int argc, char*argv[]) {int sleepMs = 3; //ms
int sleepLoop = 5000;long sleepT = sleepMs * sleepLoop * 1000;/*############## sleep ############################*/sleep(1); //sleep 1秒
/*############## 使用 usleep 做定时 #################*/showTime(1,sleepT,"usleep");for (int i = 0; i < sleepLoop; ++i) {
usleep(sleepMs* 1000); //等待单位微秒
}
showTime(2,sleepT,"usleep");/*############## 使用 select 做定时 ###################*/showTime(1,sleepT,"select");structtimeval wait_time;
gettimeofday(&tvs, 0);for (int i = 0; i < sleepLoop; i++) {
wait_time.tv_sec= 0; //秒
wait_time.tv_usec = sleepMs * 1000; //微妙
select(0, NULL, NULL, NULL, &wait_time); //使用select等待 ,10
}
showTime(2,sleepT,"select");/*############## 使用实时时钟 RTC 做定时 ################*/
//打开 RTC 时钟
intfd;int ret = openRTC(FREQ, &fd);if (0 !=ret) {
DEB_LOG("openRTC error");return -1;
}/*使用 RTC 时钟计时*/showTime(1,sleepT,"ioctl RTC");for (int i = 0; i < sleepLoop; ++i) {
rtcTimer(sleepMs, fd);/*调用定时器函数*/}
showTime(2,sleepT,"ioctl RTC");
closeRTC(fd);//关闭 RTC 时钟
return 0;
}