文件描述符饥饿和阻塞文件描述符

3
在Linux编程接口书籍中(第1367页):
信号驱动的I/O也可能存在饥饿问题,因为它同样使用了边缘触发的通知机制。相比之下,在采用级别触发通知机制的应用程序中,不一定存在饥饿考虑因素。这是因为我们可以在级别触发通知中使用阻塞文件描述符,并使用循环不断检查描述符是否就绪,然后在再次检查前对准备就绪的描述符执行一些I/O操作。
我不理解这个“阻塞”部分的含义。我认为无论是使用阻塞I/O还是非阻塞I/O都是无关紧要的。(作者在本章开头也提到无论是级别触发还是边缘触发通知,通常都使用非阻塞I/O)

我认为它的意思是,“可以使用带级别触发通知的阻塞文件描述符”,而不是“不能可靠地使用带边缘触发通知的阻塞文件描述符”。无论如何,我认为带级别触发通知的阻塞文件描述符并不总是保证不会阻塞。因此,如果你绝不想被阻塞,就使用非阻塞套接字吧。 - ninjalj
1个回答

1

SO,IO?IO是“处理事情”,所以我们可以用人类的比喻来解释。想象一下你是系统上的一个进程,为你的老板完成任务。

那么阻塞IO就像去看牙医或与客户面对面会议。在这两种情况下,当你去参加这个事件时,你离开了你的桌子,因此在回到你的桌子之前完全无法做任何其他事情。很可能,你会在等候室浪费一些时间或在会议中闲聊/等待人们到来。

阻塞IO就像这样-阻塞IO“牺牲”(我这么说是因为你失去了线程,实际上)线程来处理相关任务。在它被阻塞期间,你不能将其用于任何其他目的-它正在等待IO发生。

相比之下,非阻塞IO就像打电话一样。当你在电话上时,你可以在写Stack Overflow答案的同时进行IO!这种IO被称为异步IO-你接受IO请求并开始处理它,但可以在它们完成时处理其他请求。

现在,我最喜欢的关于这种问题的资源是c10k问题页面。我认为你是对的 - 99%的时间你都会使用非阻塞IO(事实上,你的操作系统一直在为你进行非阻塞IO),主要是因为为每个传入的IO任务使用一个完整的线程效率极低,即使在Linux中,线程和进程是相同的东西(任务)并且相当轻量级。

边缘触发和电平触发通知类型之间的区别可能更适用于非阻塞连接,因为对于阻塞情况来说,这将是无关紧要的。据我所知,边缘触发通知仅在上次请求状态更新后有新数据时才标记描述符为就绪状态,而电平触发则在有数据可用时标记描述符为就绪状态。这意味着边缘触发接口被认为有点棘手,因为你必须在看到数据时处理传入的数据,因为你不会再收到通知。理论上,这应该更有效率(更少的通知)。

所以,简而言之 - 边缘与电平准备是阻塞与非阻塞设计略有不同的考虑因素,也就是说,有几种方法可以进行非阻塞IO,而只有一种方法可以进行阻塞IO。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接