我是 linux 编程的新手,并不完全熟悉所有的同步工具,所以我想问更多知识渊博的人他们如何解决这个问题。
我有一个线程,我想通过一个循环运行。循环中的停止点将是对套接字的读取操作。我希望读取操作阻塞一段时间然后超时。但是,如果某些事件需要注意,我需要一种方法来解除读取线程的阻塞。“事件”可以是许多不同事物中的任何一种,因此我需要某种方式来告诉线程是什么导致读取解除阻塞。
我知道您可以使用信号解除阻塞的读取,但我不确定这是如何完成的。
请参阅select()系统调用。
这对于等待多个文件通道特别有用。
您可以设置套接字操作的超时时间。例子:
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));
epoll 似乎是要走的路:
epoll API 执行与 poll(2) 类似的任务:监视多个文件描述符以查看其中任何一个是否可以进行 I/O。epoll API 既可以用作边缘触发接口,也可以用作电平触发接口,并且可以很好地扩展到大量被监视的文件描述符。提供以下系统调用来创建和管理 epoll 实例:
man epoll
了解更多信息。您可能希望查看手册中的“建议使用示例”部分。
另请参阅epoll 与 select
听起来您想像select()
其他人提到的那样使用它,但是您还想要一种在某种“消息”可用时中断它的方法。中断 a 的典型方法select()
是使用self pipe 技巧。基本上,您创建一个pipe()以及管道select()
的读取文件描述符。当消息到达程序维护的队列时,将一个字节写入管道。这将导致您的选择调用返回,您将能够检查您的管道是否已准备好读取。如果是,那么您知道您有一条消息要处理(无论您的上下文中是什么),所以您处理它然后返回select()
. 更好的是,您可以让您的管道实际上是您的消息队列。如果您只是使用管道作为表示消息在您的队列中的一种方式,请确保您read()
每次都实际从管道中取出字节,否则它最终会填满并阻止您向其写入更多通知。
虽然,正如其他人所提到的,为什么不让一个线程为您的队列服务并写入套接字,而另一个线程进行读取呢?大概简单了很多。