对于支持TSN的通信协议栈和框架,我不仅需要能够以非常精确的间隔运行,而且还可以从ptpd扣除的精确时隙开始执行实时线程。
目前,我是通过将任务延迟/放弃直到开始时间来实现的。对于我的TSN通信的PoC,这已经足够了,但是对于Linux实时扩展,必须有一种更好/更有效的方法。引入的抖动约为两个Beaglebones(运行Linux 4.14.71-ti-r80#1 SMP PREEMPT)之间的800us。
我使用循环pthread同步了网络生产者任务的开始(注意:vos_前缀表示我的OS抽象方法,实际上与POSIX调用匹配):
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扩展和策略Round-Robin的Linux 4.14),这是相当不错的-但是当涉及到多个线程都执行计划的流量时无效。
对于Linux 4.1.15-ti-rt-r43#1 SMP PREEMPT RT,我计划使用SCHED_DEADLINE作为策略,但是struct sched_attr不提供启动时间参数。然后,不需要在上面的代码中进行运行时检查。但:
我如何有效地使用Linux的实时扩展使线程在确切的绝对时间运行,例如,以绝对实时“ now” + 0.0075s(例如now.0085,now.0095,now.0105)开始的每1ms运行一次…),没有上面代码的开销?