当编写一个非阻塞程序(处理多个套接字)时,某个点需要使用open(2),stat(2)文件或使用opendir(2)打开目录来打开文件,我该怎样才能确保系统调用不会阻塞?
对我而言似乎除了使用线程或fork(2)之外别无选择。
答案 0 :(得分:3)
正如Mel Nicholson回答的那样,对于基于文件描述符的所有内容,您可以使用select / poll / epoll。对于其他所有内容,您可以使用small stack的代理线程每个项目(或线程池)进行转换(通过内核调度程序)任何同步阻塞等待选择/轮询/ epoll-able异步使用eventfd或unix pipe的事件(需要可移植性)。
代理线程应该阻塞直到操作完成,然后写入eventfd或管道以唤醒select / poll / epoll。
答案 1 :(得分:2)
确实没有其他方法。
实际上还有另一种阻塞,除了线程之外无法处理,这就是页面错误。这些可能发生在程序代码,程序数据,内存分配或从文件映射的数据中。几乎不可能避免它们(实际上你可以将一些页面锁定到内存中,但它是特权操作,并且可能通过使内核在其他地方执行不良的内存管理工作而适得其反)。所以:
open
和stat
之类的内容。无论如何,网络可能会增加比这些功能更大的延迟。此外,如果您在处理网络请求期间需要读取和处理或处理和写入数据,则使用内存映射访问文件会更快,但这是阻塞的,不能无阻塞。因此,现代网络服务器倾向于坚持大多数东西的阻塞调用,并且只有足够的线程来保持CPU忙,而其他线程正在等待I / O.
大多数现代服务器都是多核的这一事实是您无论如何都需要多个线程的另一个原因。
答案 2 :(得分:0)
您可以使用poll( )
命令使用单个线程检查任意数量的套接字数据。
See here for linux details或man poll
了解您系统的详细信息。
open( )
和stat( )
将阻止在所有POSIX兼容系统中调用它们的线程,除非通过异步策略调用(如在fork
中)