[Day 20] Node 注册事件 1

前言

昨天我们聊到, node 的 JS 层中的 IO method , 在作了相应的设定後, 就利用 XXX.on 这类 node api 把事件与其回调函数注册进 libuv 了, 其中 libuv 就是 node 处理非同步 IO 的地方, 之後细聊, 今天我们先来了解, JS 把事件及其回调函数注册进 libuv 这件事的本质是甚麽。

node 架构

https://ithelp.ithome.com.tw/upload/images/20210920/201311647f36Bh0sb9.png

观察这张图, 其中 APPLICATION 就是我们平常撰写的 JS 程序码, 而 V8 则是大名鼎鼎的 JS 驱动引擎,

https://zh.wikipedia.org/wiki/V8_(JavaScript引擎)

其实如果到此为止那就是我们一般看到的网页结构。

而今天 node 在 V8 下面加上了 C++ 连接层, 此外 V8 在运行的时候可以在跑到特定 JS 程序码时联系到 C++ 连阶层的程序码。而会被 V8 驱动引擎联系到 C++ 连阶层的 JS 程序码, 我个人称之为 Node api, 而 C++ 连接层会再把透过 node api 传入的事件及其回调函数 , 注册进更底层的 Libuv

所以我们等下来看看 node API 是怎麽联系到 C++ 连接层。

正文

从昨天的进度开始往下走, 我们来看看我们注册事件的对象 socket 的本体

https://github.com/nodejs/node/blob/master/lib/net.js

在里面可以看到再标头处的引用

**const { guessHandleType } = internalBinding('util');
const { ShutdownWrap } = internalBinding('stream_wrap');
const {
  TCP,
  TCPConnectWrap,
  constants: TCPConstants
} = internalBinding('tcp_wrap');
const {
  Pipe,
  PipeConnectWrap,
  constants: PipeConstants
} = internalBinding('pipe_wrap');**

其中 TCP 创建了 handle

function createHandle(fd, is_server) {
  validateInt32(fd, 'fd', 0);
  const type = guessHandleType(fd);
  if (type === 'PIPE') {
    return new Pipe(
      is_server ? PipeConstants.SERVER : PipeConstants.SOCKET
    );
  }

  if (type === 'TCP') {
    return new TCP(
      is_server ? TCPConstants.SERVER : TCPConstants.SOCKET
    );
  }

  throw new ERR_INVALID_FD_TYPE(type);
}

handle 被放在 socket 里, 用来处理 node api

if (options.handle) {
    this._handle = options.handle; // private
    this[async_id_symbol] = getNewAsyncId(this._handle);
  } else if (options.fd !== undefined) {
    const { fd } = options;
    let err;

    // createHandle will throw ERR_INVALID_FD_TYPE if `fd` is not
    // a valid `PIPE` or `TCP` descriptor
    this._handle = createHandle(fd, false);

    err = this._handle.open(fd);
// 後略

至此我们知道了下一步就是察看 TCP 物件, 而此时发现引用 TCP 物件用的是internalBinding('tcp_wrap');

这再 V8 的意思就是引入 C++ 档案

终於, 我们找到了被 V8 驱动引擎联系到 C++ 连接层的 JS 程序码

明天进度

查看 TCP 的来源, C++连接层中的 tcp_wrap 把事件及回调函数注册到哪了 ?

明天见 !


<<:  GitHub Security - 基本安全相关功能介绍

>>:  Day 05 - Ramda

Day-11 LinearLayout

何谓布局?布局就是版面配置,而就如同制作公告栏一样,有着不同的排版方式。 接下来我会对LinearL...

[jest] Guides - Timer Mocks

前言 在我们撰写jest的时候,常常会遇到source code的function有使用到setTi...

Unity自主学习(十八):认识Unity介面(9)

昨天看完了"Transform"栏位之後,接下来"属性检视区"...

Leetcode 207. Course Schedule | 含C++笔记

这题是graph的问题。 Input 这题是大学修课挡修的问题,我是没有遇过挡修啦,所以没什麽感觉,...

【左京淳的JAVA学习笔记】第二章 阵列与列表

学习重点 一维阵列 多维阵列(阵列内含有阵列,形成多层结构) 列表(java.util.ArrayL...