3

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

我有一个线程,我想通过一个循环运行。循环中的停止点将是对套接字的读取操作。我希望读取操作阻塞一段时间然后超时。但是,如果某些事件需要注意,我需要一种方法来解除读取线程的阻塞。“事件”可以是许多不同事物中的任何一种,因此我需要某种方式来告诉线程是什么导致读取解除阻塞。

我知道您可以使用信号解除阻塞的读取,但我不确定这是如何完成的。

4

5 回答 5

3

请参阅select()系统调用。

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

于 2013-08-09T14:54:45.517 回答
3

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

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));
于 2013-08-09T15:41:50.377 回答
2

epoll 似乎是要走的路:

epoll API 执行与 poll(2) 类似的任务:监视多个文件描述符以查看其中任何一个是否可以进行 I/O。epoll API 既可以用作边缘触发接口,也可以用作电平触发接口,并且可以很好地扩展到大量被监视的文件描述符。提供以下系统调用来创建和管理 epoll 实例:

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

另请参阅epoll 与 select

于 2013-08-09T14:58:10.973 回答
1

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

虽然,正如其他人所提到的,为什么不让一个线程为您的队列服务并写入套接字,而另一个线程进行读取呢?大概简单了很多。

于 2013-08-09T15:53:46.503 回答
0

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

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

于 2013-08-09T18:21:14.470 回答