2011-02-16 69 views
1

所以我有一个嵌入式Linux设备,通过串口连接到电机控制器。我正在编写一个接口库,它使得其他程序会调用很多很好的通用函数。其中一个是运行程序,它是目前控制器的闪存盘上的功能:最好的方法来写一个超时的功能(posix C)

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 [我不想使用信号])。

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

回答

1

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

+0

选项1是我的想法。`gettimeofday()`和`time()`的问题是,如果我(或NTP)在我的函数被调用时改变了系统时间,它将随着超时而改变。对于这个函数,`select()`没有帮助,因为我没有在串口文件描述符上等待数据。 – Ryan 2011-02-16 03:46:48

0

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

alarm()的主要限制是它在整秒内处理。有很多亚秒或分秒的替代品。你应该看看setitimer()。您可能会使用nanosleep(),但您可能还需要使用线程,因为nanosleep()会阻止调用线程。这将其提升到复杂性等级。有像pthread_cond_timedwait()这样的调用也可以用于线程化程序。

您的原型int run_motor_program(int serial_fd, char *label, timeout);不会编译;您需要定义超时参数的类型。您还需要确定您的参数意味着什么 - 无论是间隔还是持续时间(超时前运行电机的秒数),还是结束时间(程序必须是Unix时间停止)。有不同的亚秒级结构,你必须谈判。您的选择很可能受您用于实现超时的系统调用的影响。

+0

我没有在上面的原型中为超时定义的类型,因为我还没有决定如何去做。有没有发送超时的“标准”或“更常见”的方式?我知道select()使用struct timeval加载的秒数/微秒数来等待。 – Ryan 2011-02-16 03:41:54