编写一个超时的函数的最佳方法(posix C)

时间:2011-02-16 03:14:02

标签: c timeout posix

所以我有一个嵌入式Linux设备通过串口连接到电机控制器。我正在编写一个接口库,它创建了许多其他程序将调用的通用函数。其中一个是运行当前在控制器闪存盘上的程序的函数:

int run_motor_program(int serial_fd, char *label, timeout);

此功能的一般伪代码是:

call write(serial_fd, "start program at `label`")
perform a couple read()'s / write()'s to check whether program has started on the motor controller
do
   /* some stuff */
while(program is running AND timeout hasn't exceeded)
If the timeout exceeded, kill motor and return timeout error

上述功能定义中的超时用于在电机控制器上运行程序时出现问题。如果电机控制器卡在比预期更长的环路中,我需要能够停止程序。

我知道跟踪超时的唯一方法是:

1)在循环之前和循环期间调用gettimeofday()以查看经过的时间是否>传递的超时值

2)调用clock_gettime(),基本上和1一样。

3)在循环之前使用timer_create()并在循环中使用timer_getoverrun()来检查时间是否已经过去(这似乎是最优雅的解决方案,但我似乎无法使用timer_getoverrun()来处理SIGEV_NONE [我不想使用信号])。

哪些(或者如果有人有任何其他建议)是处理函数超时的最佳方法?我真的只需要分辨到毫秒级。

2 个答案:

答案 0 :(得分:1)

我倾向于自己做选项1。如果不需要亚秒级粒度,那么我将使用time。通常,工作是检查IO,因此我也使用配置了超时的select

答案 1 :(得分:0)

您可以考虑使用其中一种警报信号机制。最简单和最旧的是alarm(),它在指定的秒数后调度SIGALRM信号。如果您有SIGALRM的信号处理程序,您的进程将不会死亡,但可以让您从错误中恢复。

alarm()的主要限制是它在整秒内处理。有许多亚秒或分数秒的替代品。你应该看看setitimer()。您可能使用nanosleep()但是您可能还需要使用线程,因为nanosleep()会阻塞调用线程。这使其提高了复杂程度。像pthread_cond_timedwait()这样的调用也可以在线程程序中使用。

您的原型int run_motor_program(int serial_fd, char *label, timeout);无法编译;你需要定义超时参数的类型。您还需要确定您的参数的含义 - 是时间间隔还是持续时间(超时之前运行电机的秒数)或是否为结束时间(程序必须在之后的Unix时间)停止)。您必须协商各种亚秒级结构。您的选择可能会受到您用于实施超时的系统调用的影响。