我有一个多线程的epoll服务器。
我创建一个epoll fd,然后我将让X线程处于休眠状态,等待来自 SAME epoll fd的任何事件的epoll_wait()
。
现在我的问题是:如何唤醒N个线程,N> 1&& N< X?
到目前为止,我已经使用了Linux特定的eventfd工具,并且它只有1个线程工作得很好,但现在有多个线程在等待 SAME epoll fd,出现了一个问题:< / p>
案例1)LT:如果我使用“级别触发”模式添加我的eventfd,当我写入eventfd时,所有线程将被唤醒,这就是级别触发模式的工作原理:一次fd改变状态让我们唤醒所有线程。
N = X
案例2)ET:如果我使用“边缘触发”模式添加我的eventfd,当我写入eventfd时, ONLY 1 线程将被唤醒,这就是边缘触发模式的工作原理:在我从EAGAIN
收到read(eventfd, ...);
之前,不再发生epollfd事件。
N = 1
案例3)我也尝试过自管道技巧,并且向管道写N次会唤醒N个线程。相反它不起作用:它不可靠,有时一个线程从管道中读取2个“令牌”,有时为1或3。
N = RANDOM
在我试过的所有情况下,我不能只得到N = N,我不能只唤醒N个线程,而是1或ALL,或RANDOM。
我错过了什么?有什么想法吗?
注意:我还尝试了eventfd特定的EFD_SEMAPHORE
标志,没有任何帮助。
答案 0 :(得分:1)
根据prefetching手册页。
文件描述符是可读的(select(2)readfds 参数;民意调查(2)POLLIN标志)如果计数器有 值大于0 。
通过使用EFD_NONBLOCK
标志创建eventfd:
(if)eventfd计数器具有非零值,然后是a read(2)返回包含值1的8个字节,和 计数器的值减1。
使用信号量(epoll()
标志),NONBLOCK
(poll()
标志)eventfd并等待
级别触发eventfd_write(fd, N)
或普通read()
。
使用EAGAIN
编写 N 个帖子
你想醒醒。
线程唤醒时,执行MAIL_DRIVER=smtp
。如果
如果出现MAIL_HOST=mail.mydomain.tld
错误,您可能会重新入睡
因为 N 已成功完成读取
因此 N 线程知道他们必须保持清醒。
唤醒所有线程(eventfd问题)。
答案 1 :(得分:0)
由于您主要是要退出唤醒线程,正如您在评论中澄清的那样,您可以执行以下操作:
这会唤醒第二个线程,它从管道读取数字(现在为N-1)。如果是> 1,减少它并写入自管道并退出。 ...
依此类推,最后一个帖子从管道读取1。该线程应该退出但不再写入管道。