📅  最后修改于: 2023-12-03 14:52:14.372000             🧑  作者: Mango
在编写 C 程序时,有时需要等待一段特定的时间,然后执行下一条语句。这时就需要使用一些延迟函数或定时器来实现。下面是一些实现方式的介绍。
sleep
函数是 C 标准库中的一种延迟函数,其头文件是 unistd.h
。调用 sleep
函数时,程序会阻塞指定的时间,等待时间过去之后才会继续执行。例如,下面的代码会让程序等待 10 秒钟,然后输出一条消息。
#include <unistd.h>
#include <stdio.h>
int main() {
printf("Start to sleep...\n");
sleep(10);
printf("Wake up!\n");
return 0;
}
输出结果:
Start to sleep...
Wake up!
需要注意的是,sleep
函数的精度比较低,时间很可能不是非常准确。这种方式适用于需要简单实现延迟的情况,例如在控制 LED 时等待一段时间再改变状态。
在需要更精确的时间控制时,可以使用定时器。定时器实际上是一个计时器,可以设置一个时间间隔,当计时器计满时就会触发一个事件。具体实现方式有很多种,下面是一种基于 POSIX 标准的方式。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t timer_flag = 0;
void timer_handler(int signum) {
timer_flag = 1;
}
int main() {
struct sigaction sa;
struct itimerval timer;
sa.sa_handler = timer_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);
timer.it_value.tv_sec = 5;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
while (1) {
if (timer_flag) {
printf("Timer expired!\n");
timer_flag = 0;
}
usleep(10000);
}
return 0;
}
这段代码定义了一个名为 timer_handler
的回调函数,该函数在定时器到期时被调用。在 main
函数中,我们使用 sigaction
函数来注册该回调函数,使用 setitimer
函数来设置定时器参数,然后进入一个无限循环,在循环中不断检查计时器是否到期。当计时器到期时,就会执行回调函数来进行相应的处理。
需要注意的是,计数器到期后,setitimer
默认只触发一次,如果需要重复触发,则需要在 it_interval
中设置间隔时间,单位是微秒。
另一种实现方式是使用多线程。在一个独立的线程中执行计时器逻辑,主线程继续处理其他任务。下面是一个基于 POSIX 线程的示例程序。
#include <stdio.h>
#include <pthread.h>
int count = 0;
void* timer_thread(void* args) {
int duration = *(int*)args;
while (1) {
if (count >= duration) {
printf("Timer expired!\n");
break;
}
usleep(10000);
count++;
}
return NULL;
}
int main() {
int duration = 50;
pthread_t thread;
pthread_create(&thread, NULL, timer_thread, (void*)&duration);
while (1) {
printf("Main thread is running...\n");
usleep(500000);
}
pthread_join(thread, NULL);
return 0;
}
这段代码使用 pthread_create
函数创建一个新线程,在该线程中执行 timer_thread
函数来处理定时器逻辑。在主线程中,我们不断地输出一条消息,然后等待 500 毫秒,模拟其他任务的处理。当计时器到期时,会执行 timer_thread
函数中的相关逻辑来进行相应的处理,然后结束该线程。
完整的代码见 delay.c。
以上介绍了三种实现方法:使用 sleep
函数、使用定时器、使用多线程。选择哪一种方式取决于具体的应用场景和需要延迟的粒度。在实际应用中,还需要考虑可移植性、稳定性、并发性等因素。需要根据实际情况灵活选择并合理使用不同的实现方式。