【问题标题】:Understanding libuv / epoll / non-blocking network IO了解libuv/epoll/非阻塞网络IO
【发布时间】:2018-11-07 18:58:44
【问题描述】:

我正在尝试了解非阻塞网络 IO 在Node.js/libuv 中的工作方式。我已经发现 file IO 是使用 libuv 工作线程完成的(因此,在后台线程中)。然而,在很多地方都指出 network IO 是使用 epollkqueue 等系统调用以非阻塞方式完成的(取决于操作系统)。

现在我想知道这是否意味着实际的 IO 部分 (read())仍然在主线程上完成,因此阻塞,即使 e。 G。使用epoll?至于我的理解,epoll 仅通知可用事件,但实际上并不进行读/写。至少在我发现的示例中(例如http://davmac.org/davpage/linux/async-io.htmlepoll 总是与read 系统调用结合使用,这是一个阻塞 IO 操作。

换句话说,如果libuv 使用单线程并且epoll 在数据可供读取时收到通知,那么接下来的读取操作会在主线程上执行,因此可能会阻塞其他操作(考虑网络请求)在主线程上?

【问题讨论】:

  • 其实epoll有两种模式,一般我们使用数据到达时只触发一次用户的模式,所以我们需要把socket设置成非阻塞模式。
  • Socket 处于非阻塞模式意味着read syscall 在没有数据可用时不会阻塞。那么实际的 IO 还没有在后台某处完成?
  • epoll/poll/select 都是用来对一个准备好做无阻塞操作的fd做IO操作。使用 poll/epoll/select 你可以在单个线程上使用阻塞操作进行异步操作。
  • @user826955 "所以实际的 IO 还没有在后台某处完成?"你的意思是 ? read 是实际的 IO。
  • 好吧,正如我在上面试图解释的那样,我的理解(这可能是错误的)是epoll 的返回值将指示数据是否可用,而随后的read() 实际上将从套接字读取字节。现在与libuv/Node.js相关,如果不是在单独的线程中完成,这个异步怎么办?

标签: c node.js networking io libuv


【解决方案1】:

epoll/poll/select 始终将引用文件的文件描述符报告为已准备好进行读/写,但是,read/write 可能会阻塞等待数据被读/写。这就是为什么文件 I/O 必须在单独的线程中完成的原因。

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

【讨论】:

  • 那么这是否意味着当调用recv时,可用数据已经被something(操作系统?)传输/缓冲了
  • @user826955 确实如此,是的。该数据驻留在内核套接字缓冲区中,需要复制到进程地址空间中,这就是非阻塞recv 所做的。
  • 但是复制到进程地址空间基本上与将文件内容从文件 IO 复制到进程内存中的任务相同,对吧?换句话说,使用资源/CPU 时间,而不是立即/原子地完成。我真的只是想了解异步网络 IO 与 libuv 中的异步文件 IO 有何不同,因为根据他们的文档,只有文件 IO 使用专用的后台线程进行 IO 工作。
  • @user826955 不,文件数据位于存储的其他位置,而套接字数据已被内核接收。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 2016-10-20
相关资源
最近更新 更多