1

我正在编写一个应用程序,它使用计时器以固定采样率(200Hz)进行一些数据采集和处理。该应用程序就像一个服务器并在后台运行。它应该可以从其他进程或来自 UDP 的其他机器控制。

为此,我使用 timer_create() API 定期生成 SIGUSR1 并调用执行获取和处理的处理程序。

配置定时器的代码如下(为了清楚起见减去错误检查):

sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCK_REALTIME, &sev, &timerid);
timer_settime(...)

当从 UDP 接收到“开始”命令时,将调用上面的代码。为了检查命令,我在调用 recvfrom() 系统调用的主程序中有一个无限循环。

问题是,当收到“开始”命令,然后定时器正确启动并运行(使用上面的代码)时,由于定时器发送的 SIGUSR1 信号,我得到一个“系统调用中断”错误(EINTR)中断 recvfrom() 调用。如果我检查这个特定的错误代码并忽略它,我最终会在调用 recvfrom() 时收到“连接被拒绝”错误。

所以这里是我的问题:

  1. 如何解决这个“中断的系统调用”错误,因为它似乎忽略它并重新执行 recvfrom() 不起作用?
  2. 为什么我在尝试大约 20 次后收到“连接被拒绝”错误?
  3. 我觉得使用 SIGEV_THREAD 可能是一种解决方案,据我了解,创建一个新线程(如 phread_create)而不生成信号。我对吗?
  4. 信号编号在这里重要吗?使用实时信号有什么好处吗?
  5. 有没有其他方法可以做我想做的事情:让后台循环检查来自 UDP 的命令和实时定期任务?

这里是奖金问题:

  • 在处理程序中进行数据采集和处理是否安全,或者我应该使用信号量机制来唤醒执行此操作的线程?

解决方案: 正如答案和评论中所建议的那样,使用 SA_RESTART 似乎可以解决主要问题。

解决方案 2: 在 SIGEV_SIGNAL 上使用 SIGEV_THREAD 也可以。我在某处读到使用 SIGEV_THREAD 可能需要比 SIGEV_SIGNAL 更多的资源。但是,我没有看到关于任务时间的显着差异。

4

4 回答 4

1

鉴于您使用的是 Linux,我会选择使用timerfd_create

这样你就可以只使用select(2)poll(2)epoll(7)来处理计时器事件,而不会遇到主循环中的信号处理程序的困难。

至于EINTR(中断的系统调用),只需重新启动被中断的特定系统调用即可正确处理这些问题。

于 2012-07-26T20:30:39.593 回答
1

定时器倾向于使用 SIGALARM 来实现。

包括 SIGALARM 在内的信号接收往往会导致长时间运行的系统调用提前返回,并且 EINTR 在 errno 中。

SA_RESTART 是解决此问题的一种方法,因此因收到信号而中断的系统调用将自动重新启动。另一种方法是从系统调用的 errno 中检查 EINTR,并在收到 EINTR 时重新启动它们。

使用 read() 和 write() 当然,你不能只是重新启动,你需要从你离开的地方继续。这就是为什么这些返回传输的数据长度的原因。

于 2012-07-26T20:33:08.460 回答
0

重新启动中断的系统调用是对EINTR. 您的“连接被拒绝”问题是一个不相关的错误 - 在 UDP 套接字上,它表明在该套接字上发送的先前数据包被目的地拒绝(通过 ICMP 消息通知)。

于 2012-07-27T04:36:34.400 回答
0

问题 5:您对消息和实时周期线程的使用完全没问题。但是,我建议您完全避免使用计时器,因为它们使用信号。我自己也遇到过这个问题,并最终用一个简单的clock_nanosleep() 替换了计时器,它使用TIMER_ABSTIME 更新时间以保持所需的速率(即,将周期添加到绝对时间)。结果是更简单的代码,没有更多的信号问题,并且比基于信号的计时器更准确的计时器。顺便说一句,您应该在处理程序中测量计时器的周期,以确保它足够准确。我使用计时器的经验是 8 年前,因此可能会解决准确性问题。然而,信号的其他问题是信号本身固有的,因此无法“解决”——只能解决。

此外,我认为从处理程序获取数据没有问题,它肯定会减少检索数据的延迟。

于 2012-07-27T18:49:44.630 回答