低优先级进程延迟实时进程中的串行通信(Linux)

时间:2014-08-05 23:10:55

标签: linux serial-port real-time

我有一个实时过程,通过RS232偶尔发送通信到高速摄像机。我还有其他几个实时进程占用大量CPU时间,使用CUDA在几块GPU板上进行图像处理。通常,串行通信速度非常快,每次消息和响应大约需要50 ms。但是,当后台进程忙于进行图像处理时,串行通信会慢下来,通常需要几秒钟(有时超过10秒)。

总之,在串行通信期间,如果进程B,C等非常忙,则进程A会延迟,即使进程A具有最高优先级:

  • 进程A(实时,最高优先级):偶尔的串行通信
  • 处理B,C,D等(实时,低优先级):繁重的CPU和GPU处理

当我将后台进程更改为SCHED_OTHER(非实时)进程时,串行通信速度很快;然而,这对我来说不是一个解决方案,因为后台进程需要是实时进程(当它们没有时,GPU处理跟不上高速摄像机)。

显然,串行通信依赖于系统中的一些非实时过程,而这些过程正在被我的实时后台进程所抢占。我想如果我知道哪个进程用于串行通信,我可以提高其优先级并解决问题。有谁知道串行通信是否依赖于系统上运行的任何特定进程?

我正在使用标准内核(不是PREEMPT_RT)运行RHEL 6.5。它有双核6核。

在Erki A的建议下,我抓住了一条绳索。显然这是一个select()系统调用很慢(“set roi2”是摄像机的命令,“Ok!”结尾是摄像机的响应):

write(9, "set roi2"..., 26)             = 26 <0.001106>
ioctl(9, TCSBRK, 0x1)                   = 0 <0.000263>
select(10, [9], NULL, NULL, {2, 0})     = 1 (in [9], left {0, 0}) <2.252840>
read(9, "Ok!\r\n", 4096)                = 5 <0.000092>

慢速选择()使得它看起来像相机本身响应缓慢。但是,我知道这不是真的,因为通过改变后台进程优先级如何影响速度。在这种情况下,select()是否依赖于正在运行的某个其他进程?

如果我跳过select()并执行read(),则read()系统调用速度很慢。

2 个答案:

答案 0 :(得分:4)

根据您的串行设备/驱动程序,串行通信很可能依赖于内核工作线程(kworker)将传入的串行数据从中断服务例程缓冲区转移到线路规则缓冲区。您可以增加内核工作线程的优先级,但是,工作线程处理共享工作队列。因此,增加工作线程的优先级将增加串行处理的优先级以及可能不需要优先级提升的一大堆其他内容。

您可以修改串行驱动程序以使用专用的高优先级工作队列而不是共享队列。另一个选择是使用tasklet,但是,这两个都需要修改驱动程序。

我怀疑最直接的解决方案是将com端口设置为低延迟模式,从命令行通过setserial命令:

  

setserial / dev / ttySxx low_latency

或以编程方式:

struct serial_struct serinfo;
fd = open ("/dev/ttySxx");
ioctl (fd, TIOCGSERIAL, &serinfo);
serinfo.flags |= ASYNC_LOW_LATENCY;
ioctl (fd, TIOCSSERIAL, &serinfo);
close (fd);

这将导致串行端口中断处理程序立即将传入数据传输到线路规则,而不是通过将传输数据添加到工作队列来推迟传输。在这种模式下,当你从应用程序中调用read()时,如果工作队列中有工作要刷新,你将避免read()调用休眠的可能性。这种睡眠可能是间歇性延迟的原因。

答案 1 :(得分:2)

您可以使用strace查看锁定位置。如果超过10秒,应该很容易看到。