📌  相关文章
📜  如何在 C 中做一段时间为真 (1)

📅  最后修改于: 2023-12-03 14:52:14.372000             🧑  作者: Mango

如何在 C 中做一段时间为真

在编写 C 程序时,有时需要等待一段特定的时间,然后执行下一条语句。这时就需要使用一些延迟函数或定时器来实现。下面是一些实现方式的介绍。

使用 sleep 函数

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 函数、使用定时器、使用多线程。选择哪一种方式取决于具体的应用场景和需要延迟的粒度。在实际应用中,还需要考虑可移植性、稳定性、并发性等因素。需要根据实际情况灵活选择并合理使用不同的实现方式。