了解libuv/epoll/non-blocking网络IO

了解libuv/epoll/non-blocking网络IO,c,node.js,networking,io,libuv,C,Node.js,Networking,Io,Libuv,我试图了解无阻塞网络IO在Node.js/libuv中是如何工作的。我已经发现,文件IO是使用libuv工作线程完成的(因此,在后台线程中)。然而,在不同的地方都有这样的说法:网络IO是以非阻塞方式完成的,使用系统调用,如epoll、kqueue等(取决于操作系统) 现在我想知道这是否意味着实际的IO部分(read())仍然在主线程上完成,因此即使e。gepoll?就我的理解而言,epoll只通知可用的事件,但实际上并不执行读/写操作。至少在我发现的示例中(例如,epoll总是与read系统调用

我试图了解无阻塞网络IO在
Node.js
/
libuv
中是如何工作的。我已经发现,文件IO是使用
libuv
工作线程完成的(因此,在后台线程中)。然而,在不同的地方都有这样的说法:网络IO是以非阻塞方式完成的,使用系统调用,如
epoll
kqueue
等(取决于操作系统)

现在我想知道这是否意味着实际的IO部分(
read()
)仍然在主线程上完成,因此即使e。g<是否使用代码>epoll?就我的理解而言,
epoll
只通知可用的事件,但实际上并不执行读/写操作。至少在我发现的示例中(例如,
epoll
总是与
read
系统调用结合使用,这是一种阻塞IO操作


换句话说,如果
libuv
使用单个线程和
epoll
,在数据可读取时发出通知,那么是否在主线程上执行以下读取操作,从而可能阻止其他操作(考虑网络请求)在主线程上?

引用文件的文件描述符总是通过
epoll/poll/select
报告为准备读/写,但是,
read/write
可能会阻止等待读/写数据。这就是为什么文件I/O必须在单独的线程中完成


而带有管道和套接字的非阻塞
send/recv
是真正的非阻塞,因此可以在I/O线程中完成,而不会阻塞线程。

实际上epoll有两种模式,通常我们使用的模式是在数据到达时只触发用户一次,所以我们需要将套接字置于非阻塞模式。非阻塞模式下的套接字意味着当没有可用数据时,
read
syscall将不会阻塞。因此,实际的IO仍然没有在后台的某个地方完成?epoll/poll/select都用于在fd上执行IO操作,该fd可以在不阻塞的情况下执行操作。使用poll/epoll/select,您可以使用阻塞操作在单个线程上执行异步操作。@user826955“所以实际的IO仍然没有在后台的某个地方执行?”您是什么意思?read是实际的IO。正如我试图在上面解释的,我的理解(可能是错误的)是,
epoll
的返回值将指示数据是否可用,随后的
read()
将实际从套接字读取字节。现在与
libuv
/
Node.js
相关,如果不是在单独的线程中完成,那么这是如何异步的呢?这是否意味着在调用
recv
时,可用数据已经被某个(OS?)@user826955传输/缓冲,是的。数据驻留在内核套接字缓冲区中,需要复制到进程地址空间,这就是非阻塞
recv
所做的。但是复制到进程地址空间基本上与将文件内容从文件IO复制到进程内存是相同的任务,对吗?换句话说,使用资源/CPU时间,而不是立即/原子地完成。我只是想了解异步网络IO与
libuv
中的异步文件IO的区别,因为根据他们的文档,只有文件IO使用专用的后台线程进行IO工作。@user826955不,文件数据驻留在存储的其他地方,而内核已经接收到套接字数据。