gpt4 book ai didi

c - 使用计时器时处理 'intterupted system call' 错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:26:28 25 4
gpt4 key购买 nike

我正在编写一个应用程序,它使用定时器以固定采样率 (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 信号中断了 recvfrom() 调用。如果我检查这个特定的错误代码并忽略它,我最终会在调用 recvfrom() 时收到“连接被拒绝”错误。

所以这是我的问题:

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

这里是奖金问题:

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

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

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

最佳答案

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

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

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

当然,对于 read() 和 write(),您不能只是重新开始,您需要从中断的地方继续。这就是为什么它们返回传输的数据长度的原因。

关于c - 使用计时器时处理 'intterupted system call' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11676991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com