linux c的四种定时方式(sleep/usleep/select/ioctl)
Posted chris83
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux c的四种定时方式(sleep/usleep/select/ioctl)相关的知识,希望对你有一定的参考价值。
1:sleep()
最小单位秒。
使用sleep/ulseep/select时,因为线程会进入休眠状态,再唤醒, 若单次执行问题不大,若是循环执行次数较多,则差别很大。
2:ulseep()
最小单位微秒。
3:select()
最小单位微秒,再循环体内使用时,每次使用都需要赋值。
4:rtc()
使用ioctl控制。
5:以上四种方法的使用示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> // gettimeofday sleep usleep #include <sys/types.h> // open #include <sys/stat.h> // open #include <fcntl.h> // open #include <errno.h> // error #include <unistd.h> // close #include <linux/rtc.h> // rtc_commadn RTC_IRQP_SET / RTC_PIE_ON / RTC_PIE_OFF #include <sys/ioctl.h> // 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) struct timeval 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(int fd) { /* 关闭 RTC 时钟计时 */ ioctl(fd, RTC_PIE_OFF, 0); /* 关闭 RTC 装置 */ close(fd); } /*使用ioctl的情况下的,计时器函数*/ int rtcTimer(int millseconds, int fd) { int loopNum = CALC_CNT(millseconds); unsigned long 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"); struct timeval 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 时钟 int fd; 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; }
6:执行后的时间差别
test.cc:33_showTime() usleep: [15000000us] [15812772us] test.cc:33_showTime() select: [15000000us] [15795666us] test.cc:33_showTime() ioctl RTC: [15000000us] [15259142us]
以上是关于linux c的四种定时方式(sleep/usleep/select/ioctl)的主要内容,如果未能解决你的问题,请参考以下文章