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

在linux编程接口手册中,(p.1367)

当使用信号驱动的I / O时,饥饿考虑也可以适用,因为它也提供了边缘触发的通知机制。 相比之下,饥饿考虑不一定适用于采用级别触发通知机制的应用程序。 这是因为我们可以使用具有级别触发通知的阻塞文件描述符,并使用循环连续检查描述符的准备情况,然后在再次检查就绪文件描述符之前,在就绪描述符上执行一些I / O。

我不明白这个“阻塞”部分是什么意思。 我认为我们使用阻塞I / O还是非阻塞I / O是无关紧要的。 (作者还在本章的早期提到,通常使用无阻塞I / O,而不pipe电平触发或边沿触发通知)

那么,呃呃? 那么,IO是“处理事物”,所以我们可以用人类的隐喻去。 想象一下,你是一个系统为你的老板做东西的过程。

然后阻止IO就像去看牙医或面对面与客户见面。 在这两种情况下,当你去参加这个活动的时候,你会离开你的办公桌,所以完全无法做任何事情,直到你回到办公桌前。 有机会,你会在候车室里浪费一些时间,或者在会议中闲聊,等待人们出现。

阻塞IO是这样的 – 阻止IO“牺牲”(我这样说是因为你失去了线程,有效)线程的任务。 当它被阻塞时,你不能将它用于任何其他目的 – 它正在等待这个IO发生。

非阻塞IO相反,就像在电话上。 当你在电话中时,你可以在堆栈溢出的同时写入一个答案的同时参与IO。 这样的IO被认为是异步的 – 因为你接受IO请求并开始处理它,但是可以在完成时处理其他请求。

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

边缘触发和电平触发的通知类型之间的区别可能更多地适用于非阻塞连接,因为无论如何,这对阻塞情况都是无关紧要的。 据我所知,边缘触发的通知只标记描述符准备好,当有新的数据从上次你要求一个状态更新,而水平触发标记描述符准备处理,只要有数据可用。 这意味着边缘触发的接口被认为有点棘手 ,因为当你看到它时你不得不处理传入的数据,因为你不会再被通知。 从理论上讲,这应该更有效率(更少的通知)。

所以,对于阻塞和非阻塞设计,tl; dr – edge和level准备是稍有不同的考虑因素,也就是说,有几种方法可以执行非阻塞IO,而只有一种方法可以阻塞IO。