【问题标题】:pthread_cond_timedwait() not waiting under 1 second? (Linux)pthread_cond_timedwait() 没有在 1 秒内等待? (Linux)
【发布时间】:2014-05-29 09:28:53
【问题描述】:

我编写了很好的监听 UDP 消息的功能,每当有新消息到达时,这些消息就会被添加到 FIFO 中,并且会向监听器发出信号。

如果没有其他事情可做,侦听器会等待消息。但是,它知道,在某些情况下,它应该在很短的时间内醒来。所以我编写了使用 pthread_cond_timedwait() 的代码,然后我将当前测试中的时间设置为大约 1.5 秒。

它确实等待 1 秒,然后等待功能不再阻塞。这是否意味着当前的实现不支持亚秒级(毫秒/微秒等待)?

有一点我的输出。我从 1417 毫秒开始,第一次尝试似乎要等待 1001 毫秒。然后在每次后续尝试中花费 0 或 1 毫秒,完全没有阻塞。

image transform ending with [1416272]
wait for 1417 till 1401354361 now = 1401354360
image transform ending with [415259]
wait for 416 till 1401354361 now = 1401354361
image transform ending with [414759]
wait for 415 till 1401354361 now = 1401354361
image transform ending with [414196]
wait for 415 till 1401354361 now = 1401354361
image transform ending with [413646]
wait for 414 till 1401354361 now = 1401354361
image transform ending with [413013]
wait for 414 till 1401354361 now = 1401354361
image transform ending with [412385]
wait for 413 till 1401354361 now = 1401354361
image transform ending with [411801]
wait for 412 till 1401354361 now = 1401354361
image transform ending with [411237]
wait for 412 till 1401354361 now = 1401354361
image transform ending with [410690]
wait for 411 till 1401354361 now = 1401354361
image transform ending with [410204]
wait for 411 till 1401354361 now = 1401354361
image transform ending with [409728]
wait for 410 till 1401354361 now = 1401354361
image transform ending with [409150]
wait for 410 till 1401354361 now = 1401354361
image transform ending with [408566]
wait for 409 till 1401354361 now = 1401354361
image transform ending with [408004]
...snip...
wait for 3 till 1401354361 now = 1401354361
image transform ending with [2188]
wait for 3 till 1401354361 now = 1401354361
image transform ending with [1628]
wait for 2 till 1401354361 now = 1401354361
image transform ending with [1077]
wait for 2 till 1401354361 now = 1401354361
image transform ending with [221]
wait for 1 till 1401354361 now = 1401354361

等待函数:

    void wait(int msecs)
    {
        if(msecs == -1)
        {
            pthread_cond_wait(&f_condition, &f_mutex.f_mutex);
        }
        else if(msecs > 0)
        {
            struct timeval tod;
            gettimeofday(&tod, nullptr);
            struct timespec ts;
            ts.tv_sec = tod.tv_sec + msecs / 1000;
            ts.tv_nsec = tod.tv_usec * 1000 + msecs % 1000;
            ts.tv_sec += ts.tv_nsec / 1000000000L;
            ts.tv_nsec = ts.tv_nsec % 1000000000L;

std::cerr << "wait for " << msecs << " till " << ts.tv_sec << " now = " << time(NULL) << "\n";

            pthread_cond_timedwait(&f_condition, &f_mutex.f_mutex, &ts);
        }
    }

【问题讨论】:

  • 你想发布一些代码吗? :-)
  • 当这种情况发生时,您从pthread_cond_timedwait() 看到什么返回码?
  • 好的,我添加了wait()函数本身的代码。它是在互斥锁锁定的情况下调用的。调用返回的代码是 110,代表#define ETIMEDOUT 110 /* Connection timed out */。所以它认为current time &gt;= ts...
  • 不应该是ts.tv_nsec = tod.tv_usec * 1000 + msecs * 1000 * 1000吗?您似乎是将毫秒除以 1000(即计算秒单位)然后将其添加到纳秒单位中。
  • @6EQUJ5:我想你已经找到问题了,但我认为实际的表达应该是:ts.tv_nsec = tod.tv_usec * 1000 + (msecs % 1000) * 1000 * 1000

标签: linux pthreads wait milliseconds


【解决方案1】:

我编写了很好的监听 UDP 消息的功能,每当有新消息到达时,这些消息就会被添加到 FIFO 中,并且会向监听器发出信号。

好吧,套接字缓冲区已经是一个 FIFO。因此,您从 FIFO 中取出一个 UDP 数据报,并再次将其放入 FIFO。对吗?

如果没有其他事情可做,侦听器会等待消息。然而,它知道,在某些情况下,它应该在很短的时间内醒来。因此,我编写了代码来使用 pthread_cond_timedwait(),然后我将当前测试中的时间设置为大约 1.5 秒。

为什么不直接使用 select/epoll 或类似 libevent 的 1.5 秒超时?

它确实等待 1 秒,然后等待功能不再阻塞。这是否意味着当前的实现不支持亚秒级(毫秒/微秒等待)?

您的输出很难阅读,并且对确定正在发生的事情没有帮助。您需要打印您想等待多长时间、发生了什么(超时或收到信号)以及在超时的情况下实际等待了多长时间。

【讨论】:

  • (第 1 点)确实,UDP 消息队列是一个 FIFO。我有 2 个线程,因为当工作线程继续运行并且不会检查 UDP FIFO 时,我可能会在 UDP FIFO 中收到 100 条消息。在某些时候,该 FIFO 可能已满,如果发生这种情况,我可能会错过一些事件(其中一些可能很重要,例如我用来尽快结束工作过程的 STOP 消息。)(第 2 点)因为我有两个线程,对我来说使用线程相关函数似乎是合乎逻辑的......(第 3 点)要查看的主要数字是下降的 416,一次大约 1 毫秒,在最后一条消息中最多为 1。
猜你喜欢
  • 2016-09-03
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 2012-07-30
  • 2023-04-10
  • 1970-01-01
  • 2022-06-23
相关资源
最近更新 更多