Node 底层结构探秘

摘录自nodejs真的是单线程吗?

Node.js 标准库,这部分是由 Javascript 编写的,即我们使用过程中直接能调用的 API。在源码中的 lib 目录下可以看到。

Node bindings,这一层是 Javascript 与底层 C/C++ 能够沟通的关键,前者通过 bindings 调用后者,相互交换数据。实现在 http://node.cc,这一层是支撑 Node.js 运行的关键,由 C/C++ 实现。

V8:Google 推出的 Javascript VM,也是 Node.js 为什么使用的是 Javascript 的关键,它为 Javascript 提供了在非浏览器端运行的环境,它的高效是 Node.js 之所以高效的原因之一。

Libuv:它为 Node.js 提供了跨平台,线程池,事件池,异步 I/O 等能力,是 Node.js 如此强大的关键。

C-ares:提供了异步处理 DNS 相关的能力。

http_parser、OpenSSL、zlib 等:提供包括 http 解析、SSL、数据压缩等其他的能力。

与系统底层交互

IO操作例子如操作文件 fs.open('./test.txt', "w", function(err, fd) { //..do something });

调用过程可以描述为 lib/fs.js (Node标准库) → src/node_file.cc (Node bingdings) → uv_fs (Libuv)

lib / fs.js

async function open(path, flags, mode) {
  mode = modeNum(mode, 0o666);

  path = getPathFromURL(path);

  validatePath(path);

  validateUint32(mode, "mode");

  return new FileHandle(
    await binding.openFileHandle(
      pathModule.toNamespacedPath(path),

      stringToFlags(flags),

      mode,
      kUsePromises
    )
  );
}

src/node_file.cc

static void Open(const FunctionCallbackInfo<Value>& args) {
    Environment* env = Environment::GetCurrent(args);
        const int argc = args.Length();
        if (req_wrap_async != nullptr) { // open(path, flags, mode, req)
        AsyncCall(env, req_wrap_async, args, "open", UTF8, AfterInteger,
        uv_fs_open, *path, flags, mode);
    } else { // open(path, flags, mode, undefined, ctx)
        CHECK_EQ(argc, 5);
        FSReqWrapSync req_wrap_sync;
        FS_SYNC_TRACE_BEGIN(open);
        int result = SyncCall(env, args[4], &req_wrap_sync, "open",
        uv_fs_open, *path, flags, mode);
        FS_SYNC_TRACE_END(open);
        args.GetReturnValue().Set(result);
    }
}

uv_fs

/* Open the destination file. */

dstfd = uv_fs_open(NULL,
    &fs_req,
    req->new_path,
    dst_flags,
    statsbuf.st_mode,
    NULL
);

uv_fs_req_cleanup(&fs_req);
posted @ 2020-05-08 00:07  Ever-Lose  阅读(631)  评论(0编辑  收藏  举报