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);