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