当编写一个非阻塞程序(处理多个套接字),在某个时刻需要使用open(2)打开文件,使用stat(2)检查文件或者使用opendir(2)打开目录时,如何确保系统调用不会阻塞?
在我看来,除了使用线程或fork(2),似乎没有其他选择。
当编写一个非阻塞程序(处理多个套接字),在某个时刻需要使用open(2)打开文件,使用stat(2)检查文件或者使用opendir(2)打开目录时,如何确保系统调用不会阻塞?
在我看来,除了使用线程或fork(2),似乎没有其他选择。
read
阻塞实际读取数据(write
通常不等待实际写入磁盘,但如果进行随机访问,则可能会阻塞_读取_数据)。 - Jan Hudec实际上,除了使用线程之外,还有一种无法解决的阻塞问题是页面故障。这可能发生在程序代码、程序数据、内存分配或从文件映射的数据中。几乎不可能避免它们(实际上,您可以将某些页面锁定到内存中,但这是特权操作,可能会通过使内核在其他地方处理内存管理时表现不佳而产生反效果)。因此:
open
和 stat
这样的函数上。网络可能会添加比这些函数更大的延迟。此外,如果需要在处理网络请求期间读取和处理或处理和写入数据,则使用内存映射访问文件速度更快,但这是阻塞的,无法变成非阻塞的。因此,现代网络服务器倾向于对大多数内容使用阻塞调用,只需拥有足够的线程即可在其他线程等待 I/O 时使 CPU 处于繁忙状态。
大多数现代服务器都是多核的,这也是需要多个线程的另一个原因。
您可以使用poll()
命令在单个线程中检查任意数量的套接字数据。
请参阅此处以获取Linux详细信息,或者使用man poll
命令获取您系统的详细信息。
open()
和stat()
在所有符合POSIX标准的系统中都会在调用它们的线程中阻塞,除非通过异步策略(如在fork
中)调用。
poll
来检查 open
或 stat
是否需要等待 inode 缓存填充? - Jan Hudec
open
系统调用(失败并返回errno == EINTR
)。 - Basile Starynkevitch