title: Node.js 源码分析 - 原生模块(C++模块)的注册
date: 2018-11-28 21:04:49
tags:
- Node.js
- Node.js 源码分析
- 源码分析
categories:
- Node.js 源码分析
此文最初于四年前发布在个人站上的,现迁移至此重发,原链接:https://laogen.site/nodejs/nodejs-src/register-builtin-modules/
《Node.js 源码分析》 系列目录页:https://laogen.site/nodejs/nodejs-src/index/
创新互联是一家集网站建设,东安企业网站建设,东安品牌网站建设,网站定制,东安网站建设报价,网络营销,网络优化,东安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
上一篇提到 RegisterBuiltinModules()
注册了原生 C++ 模块没有详细展开,这里就从这个函数展开。
/* src/node.cc:3066 */
void RegisterBuiltinModules() {
#define V(modname) _register_##modname();
NODE_BUILTIN_MODULES(V)
#undef V
}
首先定义了一个宏 V
为 _register_##modname()
, 可以看出 V
展开后是一个函数调用类似这样: _register_xx()
;
随后,RegisterBuiltinModules()
实际是宏 NODE_BUILTIN_MODULES(V)
来实现的,我们看看它的定义:
/* src/node_internals.h:147 */
#define NODE_BUILTIN_MODULES(V) \
NODE_BUILTIN_STANDARD_MODULES(V)
// ...
进一步查看 NODE_BUILTIN_STANDARD_MODULES(V)
的定义:
/* src/node_internals.h:106 */
#define NODE_BUILTIN_STANDARD_MODULES(V) \
V(async_wrap) \
V(buffer) \
V(cares_wrap) \
V(config) \
V(contextify) \
V(domain) \
V(fs) \
V(fs_event_wrap) \
V(heap_utils) \
V(http2) \
V(http_parser) \
V(inspector) \
V(js_stream) \
V(messaging) \
V(module_wrap) \
V(options) \
V(os) \
V(performance) \
V(pipe_wrap) \
V(process_wrap) \
V(serdes) \
V(signal_wrap) \
V(spawn_sync) \
V(stream_pipe) \
V(stream_wrap) \
V(string_decoder) \
V(symbols) \
V(tcp_wrap) \
V(timer_wrap) \
V(trace_events) \
V(tty_wrap) \
V(types) \
V(udp_wrap) \
V(url) \
V(util) \
V(uv) \
V(v8) \
V(worker) \
V(zlib)
这个宏定义中多次调用宏 V
,还记得这个宏吗,在上面定义的:#define V(modname) _register_##modname();
,那我们把它展开后就是:
/* src/node_internals.h:106 */
#define NODE_BUILTIN_STANDARD_MODULES(V) \
_register_async_wrap();
_register_buffer();
_register_cares_wrap();
_register_config();
_register_contextify();
_register_domain();
_register_fs();
_register_fs_event_wrap();
_register_heap_utils();
_register_http2();
_register_http_parser();
_register_inspector();
_register_js_stream();
_register_messaging();
_register_module_wrap();
_register_options();
_register_os();
_register_performance();
_register_pipe_wrap();
_register_process_wrap();
_register_serdes();
_register_signal_wrap();
_register_spawn_sync();
_register_stream_pipe();
_register_stream_wrap();
_register_string_decoder();
_register_symbols();
_register_tcp_wrap();
_register_timer_wrap();
_register_trace_events();
_register_tty_wrap();
_register_types();
_register_udp_wrap();
_register_url();
_register_util();
_register_uv();
_register_v8();
_register_worker();
_register_zlib();
最终,RegisterBuiltinModules()
展开后大概是这样的:
void RegisterBuiltinModules() {
_register_async_wrap();
_register_buffer();
// ...
_register_os();
// ...
}
经过层层的宏展开,我们看到 RegisterBuiltinModules()
的原貌,就是调用了一些全局注册函数,这样就能理解了。
接下来,我们打算看看这些注册函数是在哪里定义的。 我全局搜索了整个代码目录,也没找到这些函数中的任何一个,看来又是通过宏定义的。
那我们就挑一个原生模块的源码,来看看里面有没有上面注册函数的定义,我挑了模块名为 os
的模块,它的源码位于 src/node_os.cc
:
/* src/node_os.cc */
namespace node {
namespace os {
// ...
static void GetHostname(const FunctionCallbackInfo& args) {
// ...
}
static void GetOSType(const FunctionCallbackInfo& args) {
// ...
}
static void GetOSRelease(const FunctionCallbackInfo& args) {
// ...
}
static void GetCPUInfo(const FunctionCallbackInfo& args) {
// ...
}
static void GetFreeMemory(const FunctionCallbackInfo& args) {
// ...
}
static void GetTotalMemory(const FunctionCallbackInfo& args) {
// ...
}
static void GetUptime(const FunctionCallbackInfo& args) {
// ...
}
static void GetLoadAvg(const FunctionCallbackInfo& args) {
// ...
}
static void GetInterfaceAddresses(const FunctionCallbackInfo& args) {
// ...
}
static void GetHomeDirectory(const FunctionCallbackInfo& args) {
// ...
}
static void GetUserInfo(const FunctionCallbackInfo& args) {
// ...
}
static void SetPriority(const FunctionCallbackInfo& args) {
// ...
}
static void GetPriority(const FunctionCallbackInfo& args) {
// ...
}
// 这个初始化函数是每个原生模块都会定义的,它的参数也是一致的
void Initialize(Local