【源码】os.networkInterfaces调用过程
发布于 4 年前 作者 gocpplua 1531 次浏览 来自 分享

我们在js中写代码:

const os = require('os')
os.networkInterfaces()

首先,require中的‘os’模块可以找到,因为有lib/os.js。 在os.js中,找到函数"networkInterfaces":

此函数的导出: 在os.js中可以看到此函数的导出:

module.exports = {
....
  networkInterfaces,
....
};

此函数的定义:

function networkInterfaces() {
  const data = getInterfaceAddresses();
  const result = {};

  if (data === undefined)
    return result;
  for (var i = 0; i < data.length; i += 7) {
    const name = data[i];
    const entry = {
      address: data[i + 1],
      netmask: data[i + 2],
      family: data[i + 3],
      mac: data[i + 4],
      internal: data[i + 5],
      cidr: getCIDR(data[i + 1], data[i + 2], data[i + 3])
    };
    const scopeid = data[i + 6];
    if (scopeid !== -1)
      entry.scopeid = scopeid;

    const existing = result[name];
    if (existing !== undefined)
      existing.push(entry);
    else
      result[name] = [entry];
  }

  return result;
}

在定义中我们看到函数"getInterfaceAddresses",这个是通过V8导出的C++接口,在node_os.cc中看到:

void Initialize(Local<Object> target,
                Local<Value> unused,
                Local<Context> context,
                void* priv) {
  Environment* env = Environment::GetCurrent(context);
 ...
  env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
 ...
}

此文件最后:

NODE_MODULE_CONTEXT_AWARE_INTERNAL(os, node::os::Initialize)

宏定义在src\node_binding.h中,如下:

#define NODE_MODULE_CONTEXT_AWARE_INTERNAL(modname, regfunc)                   \
  NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, nullptr, NM_F_INTERNAL)

NODE_MODULE_CONTEXT_AWARE_CPP宏定义在src\node_binding.h中,如下

#define NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, priv, flags)           \
  static node::node_module _module = {                                         \
      NODE_MODULE_VERSION,                                                     \
      flags,                                                                   \
      nullptr,                                                                 \
      __FILE__,                                                                \
      nullptr,                                                                 \
      (node::addon_context_register_func)(regfunc),                            \
      NODE_STRINGIFY(modname),                                                 \
      priv,                                                                    \
      nullptr};                                                                \
  void _register_##modname() { node_module_register(&_module); }

最后一行是对模块的注册:

 void _register_##modname() { node_module_register(&_module);

那么在哪里调用的呢??

在node_binding.cc中看到宏定义:

#define V(modname) void _register_##modname();

所有注册os模块,应该是执行:V(os),那么搜一把:

// A list of built-in modules. In order to do module registration
// in node::Init(), need to add built-in modules in the following list.
// Then in binding::RegisterBuiltinModules(), it calls modules' registration
// function. This helps the built-in modules are loaded properly when
// node is built as static library. No need to depend on the
// __attribute__((constructor)) like mechanism in GCC.
#define NODE_BUILTIN_STANDARD_MODULES(V)                                       \
...
  V(fs) \
  V(os)  \                                                   
  V(pipe_wrap) 
  ...

在看这个宏定义 NODE_BUILTIN_STANDARD_MODULES 调用的地方:

#define NODE_BUILTIN_MODULES(V)                                                \
  NODE_BUILTIN_STANDARD_MODULES(V)                                             \
  NODE_BUILTIN_OPENSSL_MODULES(V)                                              \
  NODE_BUILTIN_ICU_MODULES(V)                                                  \
  NODE_BUILTIN_PROFILER_MODULES(V)                                             \
  NODE_BUILTIN_DTRACE_MODULES(V)

这个宏定义 NODE_BUILTIN_MODULES 调用,在node_binding.cc中:

// Call built-in modules' _register_<module name> function to
// do module registration explicitly.
void RegisterBuiltinModules() {
#define V(modname) _register_##modname();
  NODE_BUILTIN_MODULES(V)
#undef V
}

函数 RegisterBuiltinModules 调用,在node.cc:


int InitializeNodeWithArgs(std::vector<std::string>* argv,
                           std::vector<std::string>* exec_argv,
                           std::vector<std::string>* errors) {
  // Make sure InitializeNodeWithArgs() is called only once.
  CHECK(!init_called.exchange(true));
 ...

  // Register built-in modules
  binding::RegisterBuiltinModules();
  ...
}

接下来上层调用依次是: node::InitializeOncePerProcess -> node::Start -> wmain/ main。

而入口函数是在node_main.cc中,根据不同环境,进入不同入口: wmain/ main。

回到顶部