1

NodeJS 使用事件驱动模型,其中只有一个线程执行事件。我知道执行的第一个事件将是用户 JS 代码。来自网络服务器的nod​​eJS网站的简单示例如下

var http = require('http');

http.createServer(function (req, res) {

  res.writeHead(200, {'Content-Type': 'text/plain'});

  res.end('Hello World\n');

}).listen(1337, '127.0.0.1');

console.log('Server running at http://127.0.0.1:1337/');

执行的第一个事件将执行上述步骤。稍后,事件循环将等待事件入队。我的问题是哪个线程使事件入队?是否有一个单独的线程可以做到这一点?如果是,多个线程也可以将事件排入队列吗?

谢谢你。

4

1 回答 1

0

我的问题是哪个线程使事件入队?是否有一个单独的线程可以做到这一点?如果是,多个线程也可以将事件排入队列吗?

javascript 解释器的核心是围绕select()系统调用的循环。系统select()调用通知操作系统您的程序感兴趣的文件句柄,并且操作系统将阻止程序的执行,直到任何这些文件句柄上有事件。基本上,select()如果您的程序感兴趣的某个 I/O 通道上有数据,将返回。

在伪代码中,它看起来像这样:

while(1) {
    select(files_to_write,files_to_read,NULL,NULL,timeout)

    process_writable(files_to_write)
    process_readable(files_to_read)
    timeout = process_timers()
}

这个单一的函数允许解释器实现异步 I/O 和setTimeout/ setInterval。(从技术上讲,这只是部分正确。Node.js 使用 select 或 poll 或 epoll 等,这取决于哪些功能可用以及哪些功能在您的操作系统上更有效)

那么,谁将事件排入队列?操作系统。


有一个例外。node.js 上的磁盘 I/O 由单独的线程处理。所以对于这个 I/O,正是这个磁盘 I/O 线程将事件排入事件循环。

它可以在没有线程的情况下实现。例如,Tcl 编程语言(早于 javascript,但也有内置事件循环)使用 kqueue(在基于 BSD 的 OS,如 MacOS)或 aio(在 Linux 和其他几个操作系统上)等功能在主线程中实现磁盘 I/O操作系统)或重叠 i/o(Windows)。但是 node.js 开发人员只是选择了线程来处理磁盘 i/o。


有关这在 C 级别如何工作的更多信息,请参阅此答案:我知道回调函数异步运行,但为什么呢?

于 2015-05-17T20:15:39.317 回答