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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章