C语言 如何为C中的函数设置超时?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7738546/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set a timeout for a function in C?
提问by Devi
I have a requirement that I have to give xx ms to execute a function. After xx ms I have to abort that function. Please help me how to implement it in C.
我有一个要求,我必须给 xx ms 来执行一个函数。在 xx ms 之后,我必须中止该功能。请帮助我如何在 C 中实现它。
回答by Bobby Powers
I think the nicest way to do this involves pthreads. Start the calculation that potentially may need to be cancelled in its own thread, and in the main thread use pthread_cond_timedwait:
我认为最好的方法是使用 pthreads。在自己的线程中启动可能需要取消的计算,并在主线程中使用 pthread_cond_timedwait:
#include <time.h>
#include <pthread.h>
#include <stdio.h>
/* for ETIMEDOUT */
#include <errno.h>
#include <string.h>
pthread_mutex_t calculating = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t done = PTHREAD_COND_INITIALIZER;
void *expensive_call(void *data)
{
int oldtype;
/* allow the thread to be killed at any time */
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
/* ... calculations and expensive io here, for example:
* infinitely loop
*/
for (;;) {}
/* wake up the caller if we've completed in time */
pthread_cond_signal(&done);
return NULL;
}
/* note: this is not thread safe as it uses a global condition/mutex */
int do_or_timeout(struct timespec *max_wait)
{
struct timespec abs_time;
pthread_t tid;
int err;
pthread_mutex_lock(&calculating);
/* pthread cond_timedwait expects an absolute time to wait until */
clock_gettime(CLOCK_REALTIME, &abs_time);
abs_time.tv_sec += max_wait->tv_sec;
abs_time.tv_nsec += max_wait->tv_nsec;
pthread_create(&tid, NULL, expensive_call, NULL);
/* pthread_cond_timedwait can return spuriously: this should
* be in a loop for production code
*/
err = pthread_cond_timedwait(&done, &calculating, &abs_time);
if (err == ETIMEDOUT)
fprintf(stderr, "%s: calculation timed out\n", __func__);
if (!err)
pthread_mutex_unlock(&calculating);
return err;
}
int main()
{
struct timespec max_wait;
memset(&max_wait, 0, sizeof(max_wait));
/* wait at most 2 seconds */
max_wait.tv_sec = 2;
do_or_timeout(&max_wait);
return 0;
}
you can compile and run this on linux with:
您可以使用以下命令在 linux 上编译和运行它:
$ gcc test.c -pthread -lrt && ./a.out
do_or_timeout: calculation timed out
回答by Brandin
If you're not using pthreads you can also do a similar timeout function using the Apache Portable Runtime: http://apr.apache.org/docs/apr/1.4/group__apr__thread__proc.html
如果您不使用 pthreads,您也可以使用 Apache Portable Runtime 执行类似的超时功能:http: //apr.apache.org/docs/apr/1.4/group__apr__thread__proc.html
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "apr.h"
#include "apr_thread_proc.h"
#include "apr_time.h"
void *APR_THREAD_FUNC expensive_call(apr_thread_t *thread, void *data)
{
(void)thread;
bool *done = data;
/* ... calculations and expensive io here, for example:
* infinitely loop
*/
for (;;) {}
// signal caller that we are done
*done = true;
return NULL;
}
bool do_or_timeout(apr_pool_t *pool, apr_thread_start_t func, int max_wait_sec)
{
apr_thread_t *thread;
bool thread_done = false;
apr_thread_create(&thread, NULL, func, &thread_done, pool);
apr_time_t now = apr_time_now();
for (;;) {
if (thread_done) {
apr_thread_join(NULL, thread);
return true;
}
if (apr_time_now() >= now + apr_time_make(max_wait_sec, 0)) {
return false;
}
// avoid hogging the CPU in this thread
apr_sleep(10000);
}
}
int main(void)
{
// initialize APR
apr_initialize();
apr_pool_t *ap;
if (apr_pool_create(&ap, NULL) != APR_SUCCESS) {
exit(127);
}
// try to do the expensive call; wait up to 3 seconds
bool completed = do_or_timeout(ap, expensive_call, 3);
if (completed) {
printf("expensive_call completed\n");
} else {
printf("expensive_call timed out\n");
}
apr_terminate();
return 0;
}
Compile using a command like this
使用这样的命令编译
gcc -o example example.c -lapr-1
gcc -o 示例 example.c -lapr-1
回答by Jeegar Patel
->include time.h
->take two variable for start time & current time of type time_t
like time_t start_time,current_time
-> take start time
time(&start_time);
now in while loop continuisly check for
time(¤t_time)
difftime(current_time,start_time)
if difftime's return value is 15ms break while loop & close your program
回答by Jaros?aw Jaryszew
I do not know that architecture so I can give you only a general hint. I would try something similar to old Symbian TRAP mechanism.
我不知道那个架构,所以我只能给你一个一般性的提示。我会尝试一些类似于旧的 Symbian TRAP 机制的东西。
In the main routine:
- start a timer.
- put away a stack pointer
- put away a program counter.
- call your function.
In timer exception (interrupt) handling routine. This is a bit tricky because you need to know where in given architecture stack pointers and program counters are kept (processor's datasheet) when exception handling kicks in. Program counter was most likely pushed to the main routine stack. So your steps are:
- replace the stack pointer value (for main routine) with your copied value.
- replace the program counter value with your copied value + offset (because you want to return to execution after your function call - best to check the assembly code to be sure how big is it).
- return from exception (interrupt) handling routine.
在主程序中:
- 启动计时器。
- 收起堆栈指针
- 收起程序计数器。
- 调用你的函数。
在定时器异常(中断)处理例程中。这有点棘手,因为当异常处理开始时,您需要知道给定架构堆栈指针和程序计数器保存在何处(处理器的数据表)。程序计数器最有可能被推送到主例程堆栈。所以你的步骤是:
- 用您复制的值替换堆栈指针值(对于主程序)。
- 用您复制的值 + 偏移量替换程序计数器值(因为您想在函数调用后返回执行 - 最好检查汇编代码以确保它有多大)。
- 从异常(中断)处理例程返回。
回答by Hymany
@Bobby Powers answer is work, but need a little change as below
@Bobby Powers 的答案是可行的,但需要做一些改动,如下所示
if (!err)
pthread_mutex_unlock(&calculating);
-> change to
pthread_mutex_unlock(&calculating);
as @T.D. Smith says
and need add
pthread_cancel(tid) // if isn't add, the expensive_call may never exit if your function couldn't exit by itself, such as for (;;) {} or something block operation.

