【问题标题】:C timers and threads againC 计时器和线程再次
【发布时间】:2011-01-16 23:17:12
【问题描述】:

有人可以帮助我完成我的代码,该函数可以检查计时器“check_timer”的结果以及另一个重置此计时器(如果它已过期“reset_timer”)的结果吗?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>

#define GLOBAL_TIMER  8 * 60 * 60


typedef struct protocol_type {
 int protocol_number;
 char *protocol_name;
 pthread_t thread_timer_id;
} protocol_type_t;

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


/* call back function - inform the user the time has expired */
void timeout_call_back(pthread_t thread_id)
{
    printf("Welcome thread %ld, your time is up ===\n", pthread_self());
    // doing some other stuff
}

/* Go to sleep for a period of seconds */
static void* start_timer(void *args)
{
    /* function pointer */
    void (*finish_function)(pthread_t);


    int seconds = *((int*) args);

    finish_function = timeout_call_back;

 struct timeval now;
 struct timespec timeout;

 pthread_mutex_lock(&mut);
 printf("thread ID : %ld, are waiting for %d seconds to to expire\n", pthread_self(), seconds);
 gettimeofday(&now, NULL);
 timeout.tv_sec = now.tv_sec + seconds;
 timeout.tv_nsec = now.tv_usec * 1000;
 pthread_cond_timedwait(&cond, &mut, &timeout);
 (*finish_function)(pthread_self());
 pthread_mutex_unlock(&mut);
    pthread_exit(NULL);
}

// This function is in MT environnement and is running inside a daemon
int received_buffer_parser(char *received_buffer) {
 pthread_mutex_t mut_main = PTHREAD_MUTEX_INITIALIZER; 
 protocol_type_t *my_protocol;

 // Identify protocol type
 my_protocol = protocol_identifier(received_buffer);

 // Check if i received it in the last 8 hours in safe 
 pthread_mutex_lock(&mut_main);
    if (check_timer(my_protocol->thread_id) has expired) { // I want to write this function
  // I want to reset thread timer
   launch_new_timer(my_protocol->thread_id)
 }
 else {
  // doing some stuff
  // dump data to the disk
 }
 pthread_mutex_unlock(&mut_main);

 return 0;
}

int launch_new_timer(pthread_t thread_id)
{
 int rc;
 int seconds = GLOBAL_TIMER;

    rc =  pthread_create(&thread_id, NULL, start_timer, (void *) &seconds);
    if(rc)
     printf("Failed to create thread1\n");

    pthread_join(thread_id, NULL);

    return 0;
}

澄清

我在这里澄清我的代码的真实上下文: 我从网络收到一些不同类型的协议数据包(ICMP、SSH、RIP、OSPF、BGP...),我想:

  1. 识别每种类型的数据包,比如说:identify_protocol(char *received_buffer),我得到了这个函数,没关系。

  2. 检查我是否在过去 8 小时内收到此类协议(每种协议类型的计时器在 8 小时后过期),两种选择:

一个。如果是这样,我将结果数据转储到磁盘上的特定文件中。

b.不,我在过去 8 小时内没有收到这种类型我创建了一个新线程(在我的代码中我简化了线程 1、线程 2 和线程 3,这个线程是 3 个线程,曾经是三种协议类型的计时器) - 我使用 start_timer(void *args) 函数启动一个新的计时器来完成这项工作。

我的主要问题是如何能够以安全的方式检查我的计时器的结果,然后决定我是否重置计时器。

我在一开始就设计了finish_function来帮助我检查计时器何时到期。

请随时为我的程序提供更好的设计,以获得最佳性能。

我的系统是 Linux。

【问题讨论】:

  • 没有理由使用条件变量进行定时睡眠。只需使用nanosleep
  • 谢谢,在我的情况下如何使用 nanosleep,这是一个阻塞调用?以及我如何编写一个 check_timer 函数来检查当我收到一个新的协议包时定时器是否过期?
  • 请注意,pthread_cond_timedwait() 也是一个阻塞调用。特别是如果没有线程能够发出条件信号。
  • 另见SO 4705563。它是相关的,但又不同。
  • 那我该如何处理呢?也许我的程序设计不好。在 c 中实现一个异步计时器并不时检查它是否已过期真的很难吗?我google了很多,这个问题似乎很难!

标签: c timer pthreads


【解决方案1】:

要检查仅过期的计时器,您根本不需要使用线程和同步。只需保持全局变量指示计时器的开始时间。所以

  • 当计时器启动时,将一个全局变量(每个协议一个)设置为 gettimeofday()
  • 当你要检查某个协议的定时器是否过期时,看gettimeofday()-starttime(protocol)是否为

如果您想在计时器到期时收到通知,我建议您使用 alarm(2)。它只有第二个分辨率,但这对于 8 小时的超时应该已经足够了。每当设置、取消或重置计时器时,计算任何计时器的最小超时,然后使用该超时调用警报。在信号处理程序中,执行您想要在接收超时时执行的处理。或者,在信号处理程序中什么也不做,只相信任何挂起的系统调用都会被中断,并检查所有计时器是否在 EINTR 上到期。

编辑:闹钟是这样工作的

#include <unistd.h>
#include <signal.h>
void timeout(int ignored)
{
   printf("timed out\n");
}

void main()
{
    signal(SIGALRM, timeout);
    alarm(10);
    pause();
}

【讨论】:

  • 感谢 Martin 的回答,问题是我事先不知道我会收到哪个协议包,也不知道它们的编号(当我收到一个新包时,我只是将它添加到链表中)所以我不能每个协议都有一个全局变量!一些示例工作代码将非常有帮助:)。再次感谢。
  • 除此之外,我需要在某个协议的计时器到期时得到通知,以便我可以将他的数据文件移动到另一个目录。
  • 如果您需要按协议键入的计时器,请制作一个正在运行的计时器的链接列表。通过增加超时保持列表排序。始终调用 alarm() 以获得最小的超时值。
  • 好的,谢谢,如何拨打警报通知我计时器已过期,以便我停止将数据转储到特定文件并创建一个新文件?
  • 另外,使用time_t还是struct timeval更好?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多