假设我正在同步I / O套接字上执行I / O,该套接字已准备好进行read
或write
操作。这意味着无论套接字的非阻塞(SOCK_NONBLOCK
)/阻塞性质如何,调用线程都不会在操作上被阻塞。但是我不清楚以下事情-
read
命令时传输数据吗?它是否取决于socket的家庭?更新:
使用套接字硬件时,我错了,我在考虑下面的实际数据传输。我知道套接字不是问题,而只是OS中的一个实体,它表示适合通信的文件描述符。
后续问题-这也意味着在write
期间,调用线程将数据写入内存。是否有一个内核线程将负责在套接字的另一侧传输数据?如果是,那么套接字的异步io与同步io有何不同?
答案 0 :(得分:2)
通常,您可以将套接字I / O视为两级缓冲系统。您的应用程序中有缓冲区,然后有内核缓冲区。因此,当您调用read()时,内核会将数据从内核缓冲区复制到应用程序缓冲区。相应地,当您调用write()时,您正在将数据从应用程序缓冲区复制到内核缓冲区。
然后,内核告诉NIC将传入数据写入内核缓冲区,并从内核缓冲区读取传出数据。该I / O通常是由DMA驱动的AFAIK,这意味着内核只需要告诉NIC该做什么,而NIC负责实际的数据传输。当NIC完成时,它将引发一个中断(或者,对于高IO速率,将禁用中断,而是由内核轮询),从而导致接收到该中断的CPU内核停止执行正在执行的任何操作(用户代码,内核代码) (除非禁用了中断,否则将在队列中排队)),然后执行中断处理程序,该处理程序将负责其他需要完成的步骤。
因此,为回答您的后续问题,通常在内核侧没有单独的内核线程处理套接字I / O,工作由NIC硬件并在中断上下文中完成。
对于异步I / O或更确切地说是非阻塞I / O,唯一的区别是如何完成从用户应用程序缓冲区和内核缓冲区的复制。对于非阻塞读取,仅将内核缓冲区中准备好并等待的数据复制到用户空间(这可能会导致短读取),或者如果没有数据准备好,则read()调用将立即使用EAGAIN返回。同样,对于非阻塞write(),它仅复制与内核缓冲区中可用空间一样多的数据,这可能会导致写入时间短,或者如果根本没有可用空间,则使用EAGAIN返回。对于阻塞read(),如果没有可用数据,则调用将一直阻塞,直到有可用数据为止;而对于阻塞write(),如果内核缓冲区已满,则它将进行阻塞,直到有可用空间为止。>