У меня есть требование, чтобы я должен был дать xx ms для выполнения функции. После xx ms я должен прервать эту функцию. Пожалуйста, помогите мне, как реализовать его в C.
Как установить тайм-аут для функции в C?
Ответ 1
Я думаю, что самый лучший способ сделать это - 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;
}
вы можете скомпилировать и запустить это на linux с помощью:
$ gcc test.c -pthread -lrt && ./a.out
do_or_timeout: calculation timed out
Ответ 2
Если вы не используете 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;
}
Скомпилируйте с помощью такой команды
gcc -o example example.c -lapr-1
Ответ 3
->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 return value is 15ms break while loop & close your program
Ответ 4
Я не знаю, что такое архитектура, поэтому я могу дать вам только общий намек. Я бы попробовал что-то похожее на старый механизм Symbian TRAP.
-
В основной процедуре:
- Запустите таймер.
- убрать указатель стека
- уберите счетчик программ.
- вызов вашей функции.
-
В процедуре обработки исключения таймера (прерывания). Это немного сложно, потому что вам нужно знать, где хранятся указатели стека в стеке и счетчики программ (информация о процессоре), когда обработка исключений срабатывает. Счетчик программ, скорее всего, переместился в основной стек стека. Итак, ваши шаги:
- замените значение указателя стека (для основной процедуры) с вашим скопированным значением.
- замените значение счетчика программ на ваше скопированное значение + смещение (потому что вы хотите вернуться к выполнению после вызова функции - лучше всего проверить код сборки, чтобы убедиться, насколько он большой).
- Возврат из процедуры обработки исключений (прерываний).