在没有轮询的情况下等待多个事件

时间:2013-08-09 14:51:52

标签: c linux

我是linux编程的新手,并不完全熟悉所有的同步设施,所以我想向更多知识渊博的人询问他们如何解决这个问题。

我有一个我希望通过循环运行的线程。循环中的停止点将是套接字上的读取操作。我希望读操作阻塞一段时间然后超时。但是,如果某些事件需要注意,我需要一种方法从读取中取消阻塞线程。 “事件”可以是许多不同的东西中的任何一个,所以我需要一些方法告诉线程读取解除阻塞的原因。

我知道您可以使用信号取消阻止被阻止的读取,但我不确定这是怎么做的。

5 个答案:

答案 0 :(得分:3)

请参阅select()系统调用。

这对于等待多个文件通道特别有用。

答案 1 :(得分:2)

您可以设置套接字操作的超时。例如:

struct timeval timeout;    
timeout.tv_sec = TIMEOUT_SEC;
timeout.tv_usec = TIMEOUT_MSEC;

setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

/* now receive msg */
recvmsg(sock_fd, &msg, 0);

如果要阻止套接字,请执行以下操作:

timeout.tv_sec = 0;
timeout.tv_usec = 0;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

答案 2 :(得分:1)

epoll似乎是要走的路:

  

epoll API执行与poll(2)类似的任务:监视多个          文件描述符,以查看其中任何一个是否可以进行I / O. epoll          API既可以用作边沿触发,也可以用作电平触发的          面对并大规模地观察大量观察文件描述符。该          提供以下系统调用以创建和管理epoll          实例:

man epoll了解更多信息。您可能希望在手册中看到“建议用法示例”部分。

另见epoll vs select

答案 3 :(得分:0)

听起来你想像其他人提到的那样使用select(),但是你也想要一种在"消息"某种可用的。中断select()的典型方法是使用self pipe trick。基本上,您在管道的读取文件描述符上创建pipe()select()。当消息到达程序维护的队列时,将一个字节写入管道。这将导致您的选择呼叫返回,您将能够检查您的管道是否准备好阅读。如果是,那么您知道您有要处理的消息(无论您在上下文中是什么),所以您要处理它然后返回select()。更好的是,你可以让你的管道实际上是你的消息队列。如果您只是使用管道来表示消息在队列中,请确保每次都通过管道实际read()字节,否则它将最终填满并阻止您编写更多通知它。

虽然正如其他人所提到的,为什么不只是让一个线程服务你的队列并对套接字进行写操作,而另一个线程执行读操作?可能要简单得多。

答案 4 :(得分:0)

也许这两个库可能对您有用:

他们都在一个或多个线程上使用事件驱动的范例(如果需要的话)。当然,您可以使用已经提到的API和条件变量来实现自己的事件驱动框架,但这可能比必要的工作更多。