这是关于等待允许上下文切换的IO的呼叫,或者是非阻塞呼叫模型:
编辑:这是一个广泛而具体的问题。它是关于IO设备和CPU,操作系统用它来完成工作 - 所以请回答你的意思。它的内存也是因为每个IO操作都有内存涉及数据(如果不是寻址)。 x86和/或广泛分类的答案可以。对于设备,您可以在x86上选择网络/存储。
答案 0 :(得分:2)
一般来说,阻塞I / O调用会这样做:1)将进程/线程放在等待I / O完成的进程/线程列表上,2)将其标记为不可运行, 3)调用上下文切换。由于进行阻塞调用的线程现在被标记为不可运行,因此OS的调度程序将永远不会将其安排在CPU上运行,直到 I / O操作完成,并且线程被标记再次可以运行。这就是“阻止”实际意味着什么。
Linux有一个用于非阻塞I / O调用的接口,其工作方式大致如下:您的程序首先进行系统调用以创建“异步I / O上下文”。这是一个对象,它包含I / O操作完成时生成的通知事件的队列。内核传回一个AIO上下文标识符,程序在进行后续调用时会使用该标识符。然后,当您想要执行某些I / O时,进行另一个系统调用以“提交”异步I / O操作以执行。您可以根据需要提交尽可能多的这些内容。完成后,通知将在您的AIO上下文的事件队列中累积。稍后,只要您愿意,您可以再次进行系统调用以从该队列中检索通知。
(有趣的是,尽管Linux已经支持这些系统调用一段时间了,但它们仍未被Glibc使用!Glibc通过内部生成工作线程并在工作线程中执行阻塞I / O操作来实现非阻塞I / O !)
基本上有3例。在x86上,有IN
和OUT
指令,用于将1/2/4字节传输到硬件设备或从硬件设备传输。 x86具有用于“I / O端口”的特殊16位地址空间,可通过这些指令访问。 (我不知道其他任何架构是否也有特殊的I / O地址空间。)即使在x86上,并非所有硬件设备都映射到该I / O地址空间。有些使用常规内存地址空间。在这种情况下,您可以使用普通的MOV
指令或任何其他访问内存的指令向/从它们传输数据。第三种情况是使用DMA(直接存储器访问)时。基本上,您使用前面提到的两种方法之一向硬件设备发送某种命令,告诉它:“从地址Y开始将X字节直接传输到RAM”。然后,设备直接通过系统总线发送请求的数据并将其存储在RAM中,无需CPU的任何干预。完成后,通常会产生中断让你知道。
这完全取决于设备。没有一般性的答案。
嗯,对于Linux来说,这是我能给你的最接近答案的答案。 (不要问我其他操作系统。)在Linux中,每个存储设备都有自己的未完成I / O请求队列。每个队列都有一个名为nr_requests
的变量,它是它将保留的最大未完成I / O请求数。您可以通过打印此伪文件来查找硬盘驱动器的值:/sys/block/<DEVICE>/queue/nr_requests
。默认值似乎是128.从阅读源代码来看,似乎128也是最大值(?)。
后记:如果您正在考虑在所有您感兴趣的操作系统和硬件平台上编写一些超高性能I / O服务器应用程序或其他东西,BENCHMARK!您可以编写几个简单的测试程序,这些程序产生一堆线程(使数字可配置)并以每秒(可配置)速率启动(可配置)数量的I / O操作。观察它们完成所需的时间,服务器在测试运行时如何响应,以及有多少操作错误。