使用 posix 个线程循环执行任务

Execute a task cyclic using posix threads

我正在寻找每 20 毫秒 启动 一个方法的解决方案。我找到了一些适用于 c++ 的解决方案,但仍在寻找使用 posix 线程的 c 中的解决方案。 我不想执行该方法并等待 n 毫秒,因为这需要 20 毫秒 + X。我真的想每 20 毫秒开始一次。有人知道吗?

timer_create()timer_settime()(使用 it_interval)和 sigsuspend()——假设该方法没有超过 20 毫秒的时间间隔。

for n milliseconds as this will take 20ms + X

总是需要多一点时间。您唯一能做的就是精确测量执行之间的 间隔

使用timer_create()并指定间隔为20毫秒:

#define _GNU_SOURCE
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#define fatal(fmt, ...) do{ fprintf(stderr, "%d:%d" fmt "\n", __LINE__, errno, ##__VA_ARGS__); abort(); } while(0)

void method(union sigval sv) {
    int *num = sv.sival_ptr;
    printf("Hello %d\n", (*num)++);
}

int main() {
    int ctx = 100;
    struct sigevent sevp = {
       .sigev_notify = SIGEV_THREAD,
       .sigev_notify_function = method,
       .sigev_value = {
           .sival_ptr = &ctx,
       },
    };
    timer_t tm;
    int err = timer_create(CLOCK_MONOTONIC, &sevp, &tm);
    if (err) fatal("timer_create");
    const struct timespec ts_20_ms = {
        .tv_sec = 0,
        .tv_nsec = 20000000,
    };
    err = timer_settime(tm, 0, &(const struct itimerspec){
        .it_interval = ts_20_ms,
        .it_value = ts_20_ms,
    }, NULL);
    if (err) fatal("timer_settime");
    usleep(1 * 1000 * 1000);
    err = timer_delete(tm);
    if (err) fatal("timer_delete");
    exit(0);
}

clock_nanosleep()POSIX函数有绝对截止时间模式:

#define NSEC_PER_SEC 1000000000
/* Initial delay, 7.5ms */
const long start_delay_ns = 7500000;
/* Cycle time, 20ms */
const long cycle_time_ns = 20000000;
struct timespec deadline;

clock_gettime(CLOCK_MONOTONIC, &deadline);
deadline.tv_nsec += start_delay_ns;
deadline.tv_sec += deadline.tv_nsec / NSEC_PER_SEC;
deadline.tv_nsec %= NSEC_PER_SEC;

for (;;)
{
    struct timespec now;

    /* Sleep until deadline */
    while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &deadline, NULL) != 0)
        if (errno != EINTR)
            return; /* error handling here */

    cyclic_function(arguments);    /* Your cyclic function */

    /* Calculate next deadline */
    deadline.tv_nsec += cycle_time_ns;
    deadline.tv_sec += deadline.tv_nsec / NSEC_PER_SEC;
    deadline.tv_nsec %= NSEC_PER_SEC;

    clock_gettime(CLOCK_MONOTONIC, &now);
    if (now.tv_sec > deadline.tv_sec || (now.tv_sec == deadline.tv_sec && deadline.tv_nsec > now.tv_nsec))
        return; /* time overrun error handling here */
}