使用 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 */
}
我正在寻找每 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 */
}