aka*_*kar 4 javascript io concurrency operating-system node.js
我知道nodejs使用libuv提供的线程池来执行并发作业。我读到 NodeJS 只需要其中一个线程来完成所有 I/O 绑定活动
那么非阻塞文件操作是如何发生的呢?
如果我迭代一个包含 100 个文件的文件夹并使用 readFile() 打开所有文件,那么在节点、磁盘和操作系统之间实际上会发生什么?
如果在其他多线程和阻塞语言中执行相同的操作将导致线程等待 i/o 完成,那么谁在 nodejs 中等待 i/o 完成呢?,特别是当多个文件操作同时发生时?
谢谢 !
Nodejs中的文件IO使用线程池。默认情况下,池中有 4 个线程。
当某些 Javascript 调用文件操作(例如fs.open()在 Node.js 中)时,该调用将被路由到 Node.js 实现中的 libuv 库中的某些本机代码。该代码将特定的文件操作添加到等待操作系统线程的项目队列中。如果操作系统线程立即可用,则该操作系统线程将被赋予执行文件操作的任务,然后原始 libuv 函数返回,该函数将返回到原始 Javascript,并且 nodejs 继续运行其他 Javascript。
然后,过了一段时间,线程完成文件操作并得到结果。它将一个事件插入到nodejs事件队列中,其中包含完成的结果以及随原始文件操作传递的原始回调。
当nodejs 完成执行它正在运行的任何其他Javascript 时,它会从事件队列中提取下一个事件,并调用与该事件关联的Javascript 回调,并向其传递与该事件关联的数据。这会触发最初传递给fs.open()调用的 Javascript 回调。
如果在上面的第二步中,线程池中没有可用线程,则该任务将被添加到队列中,libuv 立即将控制权返回给 nodejs,以便它可以运行其他 Javascript。稍后,当池中的一个现有线程完成并完成将事件添加到事件队列的工作时,它将从线程池队列中拉出下一个项目,给它现在可用的线程并让它开始运行其操作。
通过这种方式,从 Javascript 方面来看,所有文件操作似乎都是非阻塞和异步的。如果线程池中有可用线程,它们要么立即启动,要么坐在线程池队列中,直到有可用线程为止。这部分对于 Javascript 方面来说是不可见的。无论哪种方式,操作都会被启动或排队,控制权会立即返回到nodejs以继续运行其他Javascript。而且,无论哪种方式,操作都会稍后完成,并且通过 Javascript 事件队列调用与文件操作关联的 Javascript 回调。这提供了 Nodejs 用于所有文件 I/O 的异步、非阻塞、事件驱动机制。