Node 底层结构探秘
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);