首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调度一个具有绝对开始时间的实时任务?

如何调度一个具有绝对开始时间的实时任务?
EN

Stack Overflow用户
提问于 2019-01-18 01:15:50
回答 1查看 370关注 0票数 1

对于TSN感知的通信协议栈和框架,我不仅需要能够以非常精确的时间间隔执行实时线程,而且需要能够以从ptpd中扣除的精确时隙开始运行。

目前,我通过将任务延迟/放弃到开始时间来做到这一点。对于我的TSN通信的PoC来说,这已经足够了,但是对于Linux实时扩展,必须有更好/更有效的方法。在两个Beaglebone之间引入的抖动大约是800us (运行Linux 4.14.71-ti-r80 #1 SMP抢占)。

使用循环pthread,我同步了我的网络生产者任务的开始(注意: vos_前缀表示我的操作系统抽象方法,实际上与POSIX调用相匹配):

代码语言:javascript
复制
for (;; )
{
    /* Synchronize with starttime */
    vos_getTime(&now);                      /* get initial time */
    vos_subTime(&now, &startTime);

    /* Wait for multiples of interval */

    execTime = ((UINT32)now.tv_usec % interval);
    waitingTime = interval - execTime;
    if (waitingTime >= interval)
    {
        ...error checks omitted
    }

    /* Idle for the difference */
    vos_threadDelay(waitingTime); /* pthread_testcancel() inside */

    vos_getTime(&priorCall);  /* get initial time */
    pFunction(pArguments);    /* thread function: send data */
    vos_getTime(&afterCall);  /* get time after function has returned */

    /* get the runtime of pFunction() */
    vos_subTime(&afterCall, &priorCall);

    /* afterCall holds now the time difference... */
    if (afterCall.tv_sec <= MAXSEC_FOR_USECPRESENTATION)
    {
        ...runtime / error handling omitted
    }
}

上面的代码以5ms的间隔时间产生大约800us的抖动(使用没有RT-extension和策略轮询的Linux4.14),这是相当好的-但当涉及到多个线程都在进行计划的流量时,这是无效的...

对于Linux4.1.15-ti-RT-r43#1SMP PREEMPT RT,我计划使用SCHED_DEADLINE作为策略,但是struct sched_attr没有提供开始时间参数。然后,就不需要在上面的代码中执行运行时检查了。但是:

我如何有效地使用Linux的实时扩展来让线程在精确的绝对时间运行,比如每1ms以绝对实时'now‘+ 0.0075s (例如now.0085,now.0095,now.0105 ...)开始运行,而不会产生上述代码的开销?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-21 13:26:10

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

代码语言:javascript
复制
#define NSEC_PER_SEC 1000000000
/* Initial delay, 7.5ms */
const long start_delay_ns = 7500000;
/* Cycle time, 1ms */
const long cycle_time_ns = 1000000;
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 */

    pFunction(pArguments);    /* thread function: send data */

    /* 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 */
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54241080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档