昨天, 我们知道了 JS 层藉由 V8 引用 C++ 层, C++ 层又利用 AIO (非同步IO) 注册事件, 接着我们就来看看负责处理事件的 libuv 在做甚麽吧。
https://github.com/nodejs/node/blob/master/src/node_main.cc
来到 C++ 层的运行起点
int main(int argc, char* argv[]) {
#if defined(__POSIX__) && defined(NODE_SHARED_MODE)
// In node::PlatformInit(), we squash all signal handlers for non-shared lib
// build. In order to run test cases against shared lib build, we also need
// to do the same thing for shared lib build here, but only for SIGPIPE for
// now. If node::PlatformInit() is moved to here, then this section could be
// removed.
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, nullptr);
}
#endif
#if defined(__linux__)
node::per_process::linux_at_secure = getauxval(AT_SECURE);
#endif
// Disable stdio buffering, it interacts poorly with printf()
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
return node::Start(argc, argv);
}
重点其实就是最後的 node::Start(argc, argv);
int Start(int argc, char** argv) {
InitializationResult result = InitializeOncePerProcess(argc, argv);
if (result.early_return) {
return result.exit_code;
}
{
Isolate::CreateParams params;
const std::vector<size_t>* indices = nullptr;
const EnvSerializeInfo* env_info = nullptr;
bool use_node_snapshot =
per_process::cli_options->per_isolate->node_snapshot;
if (use_node_snapshot) {
v8::StartupData* blob = NodeMainInstance::GetEmbeddedSnapshotBlob();
if (blob != nullptr) {
params.snapshot_blob = blob;
indices = NodeMainInstance::GetIsolateDataIndices();
env_info = NodeMainInstance::GetEnvSerializeInfo();
}
}
uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME);
NodeMainInstance main_instance(¶ms,
uv_default_loop(),
per_process::v8_platform.Platform(),
result.args,
result.exec_args,
indices);
result.exit_code = main_instance.Run(env_info);
}
TearDownOncePerProcess();
return result.exit_code;
}
可以看到实体化了一个 NodeMainInstance , 接着调用了该物件的 Run
void NodeMainInstance::Run(int* exit_code, Environment* env) {
if (*exit_code == 0) {
LoadEnvironment(env, StartExecutionCallback{});
*exit_code = SpinEventLoop(env).FromMaybe(1);
}
ResetStdio();
// TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
// make sense here.
#if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
struct sigaction act;
memset(&act, 0, sizeof(act));
for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
continue;
act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
CHECK_EQ(0, sigaction(nr, &act, nullptr));
}
#endif
#if defined(LEAK_SANITIZER)
__lsan_do_leak_check();
#endif
}
找到 SpinEventLoop 这就是 Event loop (libuv) 的创建入口
补充 : LoadEnvironment(env, StartExecutionCallback{}); 这聚会往上创建 JS 层, 但基於主体, 不深入细讲。
所以可以视为, 这个函数里面的两句, 分别往上建立 JS 层, 和往下建立 libuv 层
// Runs the main loop for a given Environment. This roughly performs the
// following steps:
// 1. Call uv_run() on the event loop until it is drained.
// 2. Call platform->DrainTasks() on the associated platform/isolate.
// 3. If the event loop is alive again, go to Step 1.
// 4. Call EmitProcessBeforeExit().
// 5. If the event loop is alive again, go to Step 1.
// 6. Call EmitProcessExit() and forward the return value.
// If at any point node::Stop() is called, the function will attempt to return
// as soon as possible, returning an empty `Maybe`.
// This function only works if `env` has an associated `MultiIsolatePlatform`.
NODE_EXTERN v8::Maybe<int> SpinEventLoop(Environment* env);
查看注解可以得知其会运行 uv_run() method , 而这就是 libuv 的核心循环。
而这句函式, 就是从 C++ 层走入 libuv 的入口。
今天从 C++ 层调用了外部方法准备运行 uv_run() , 这据说是 libuv 的核心循环, 明天一起来看看吧 !
明天见 !
(五)员工 我们目前拥有多名员工,分别是管理阶层、软件开发、硬体维护、营业部门、客户管理及财务和管理...
在有namespace的module内访问全域内容(Global Assets): 如果你希望使用全...
讲到团队(Team),就会先讲到团体(Group)这个字,谈团队之前,其实要先这样想:根本没有团队这...
半夜睡不着来更新XD Python属於「物件导向程序语言」(Object-oriented prog...
NodeList 与 HTMLCollection 的主要差异点是节点的类型不一样: NodeLi...