Nodejs源碼系列


一直想着看Nodej源碼,斷斷續續的折騰了一下,但總串不起來,太久不看又忘記。決心每天看一點,特地記錄在這里,作為逼迫自己的動力。 

2019/09/22 一、源碼編譯

之前在電腦上了下源碼,源碼目錄截圖:

 編譯通過了,編譯命令:make -j4

嘗試修改下源碼文件:lib/http.js,加入一行打印代碼:

之后,編譯 make -j4,第一次編譯會花點時間,之后編譯會快很多。編譯之后,在當前目錄下生成out/Release目錄。

看看修改的代碼是不是有效:

cd out/Release
./node
require('http')

可以看到打印出了required http haha,修改成功。

 

2019/09/23 二、node進程啟動

入口文件:src/node_main.cc,

 
  _WIN32 用來判斷是否是windows平台。
  之后還有 __linux__、__POSIX__ 這樣的宏,但都不屬於mac上的宏,所以這部分可以先忽略。值得注意的是NODE_SHARED_MODE定義在node.gypi里,不太懂。(2019/09/28 增加)
 
然后進入main函數 :
設置標准輸出、標准錯誤輸出不帶緩沖,立即輸出到控制台:
  // 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);

 

再調用了node::Start函數,傳入參數。

int main(int argc, char* argv[]) {
 ...

return node::Start(argc, argv); }

 比如說使用 node /xxxx/test.js 執行時,argc是2,argv則是['/xxxx/node', '/xxxx/test.js'],第一個是node的執行路徑。

 

再來看node::Start函數在src/node.cc文件:

int Start(int argc, char** argv) {
    atexit([] () { uv_tty_reset_mode(); }); // 注冊退出時執行的函數
    
    PlatformInit(); // 平台初始化,在mac上好像可以略過
    performance::performance_node_start = PERFORMANCE_NOW(); // 簡單理解為當前時間
    argv = uv_setup_args(argc, argv);//存儲參數Store the program arguments. Required for uv_get_process_title/uv_set_process_title argv還是沒變
  std::vector<std::string> args(argv, argv + argc);  // 創建argv的拷貝
  std::vector<std::string> exec_args;
  // This needs to run *before* V8::Initialize().
  Init(&args, &exec_args);
 ... v8_platform.Initialize( per_process_opts->v8_thread_pool_size); V8::Initialize(); performance::performance_v8_start = PERFORMANCE_NOW(); v8_initialized = true;
const int exit_code = Start(uv_default_loop(), args, exec_args);
v8_platform.StopTracingAgent(); v8_initialized
= false; V8::Dispose(); v8_platform.Dispose(); return exit_code; }

可以大概看出流程:

一、Init函數初始化了些什么東西。

Init函數挺有意思,

void Init(std::vector<std::string>* argv,
          std::vector<std::string>* exec_argv) {
  // Initialize prog_start_time to get relative uptime.
  prog_start_time = static_cast<double>(uv_now(uv_default_loop()));

  // Register built-in modules
  RegisterBuiltinModules();
其中的RegisterBuiltinModules定義如下:
void RegisterBuiltinModules() {
#define V(modname) _register_##modname();
  NODE_BUILTIN_MODULES(V)
#undef V
}

只是調用了NODE_BUILTIN_MODULES,傳入了一個宏定義。而 NODE_BUILTING_MODULES定義在node_internals.h頭文件:

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

NODE_BUILTIN_STANDARD_MODULES:
#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)

宏之間的互相調用,但是在node_internals.h里找不到async_wrap的定義,不知道在哪里定義的。(2019/09/28 增加)

 

 

二、初始化v8引擎。

三、調用Start函數,傳入事件循環。具體看Start函數。

 

Start函數還是在node.cc文件:

inline int Start(uv_loop_t* event_loop,
                 const std::vector<std::string>& args,
                 const std::vector<std::string>& exec_args) {
 ...
Isolate* const isolate = NewIsolate(allocator.get()); { Mutex::ScopedLock scoped_lock(node_isolate_mutex); CHECK_NULL(node_isolate); node_isolate = isolate; } int exit_code; {
  ...
// 又調用了重載函數 exit_code = Start(isolate, isolate_data.get(), args, exec_args); }  ... isolate->Dispose(); return exit_code; }

 

找到重載函數Start:

inline int Start(Isolate* isolate, IsolateData* isolate_data,
                 const std::vector<std::string>& args,
                 const std::vector<std::string>& exec_args) {
  HandleScope handle_scope(isolate);
  Local<Context> context = NewContext(isolate);
  Context::Scope context_scope(context);
  Environment env(isolate_data, context, v8_platform.GetTracingAgentWriter());
  env.Start(args, exec_args, v8_is_profiling);

  const char* path = args.size() > 1 ? args[1].c_str() : nullptr;
  ...
  {
    Environment::AsyncCallbackScope callback_scope(&env);
    env.async_hooks()->push_async_ids(1, 0);
    LoadEnvironment(&env);
    env.async_hooks()->pop_async_id(1);
  }
}

繼續LoadEnvironment函數。

 

LoadEnvironment函數:

void LoadEnvironment(Environment* env) {
  HandleScope handle_scope(env->isolate());
  ...
// 讀internal/bootstrap/loaders.js文件內容 Local<String> loaders_name = FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/loaders.js");

// 包裹剛才讀取的loaders.js內容 MaybeLocal
<Function> loaders_bootstrapper = GetBootstrapper(env, LoadersBootstrapperSource(env), loaders_name);

 // 讀取node.js文件內容 Local
<String> node_name = FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/node.js");

// 包裹node.js, MaybeLocal
<Function> node_bootstrapper = GetBootstrapper(env, NodeBootstrapperSource(env), node_name); Local<Value> loaders_bootstrapper_args[] = { env->process_object(), get_binding_fn, get_linked_binding_fn, get_internal_binding_fn, Boolean::New(env->isolate(), env->options()->debug_options->break_node_first_line) }; // Bootstrap internal loaders Local<Value> bootstrapped_loaders;
// 執行loaders.js,得到一個對象:{
internalBinding, NativeModule }
if (!ExecuteBootstrapper(env, loaders_bootstrapper.ToLocalChecked(),
                           arraysize(loaders_bootstrapper_args),
                           loaders_bootstrapper_args,
                           &bootstrapped_loaders)) {
    return;
  }

  // Bootstrap Node.js
  Local<Object> bootstrapper = Object::New(env->isolate());
  SetupBootstrapObject(env, bootstrapper);
  Local<Value> bootstrapped_node;
  Local<Value> node_bootstrapper_args[] = {
    env->process_object(),
    bootstrapper,
    bootstrapped_loaders
  };
// node.js是一系列的函數調用,設置node進程全局變量,如設置process對象屬性值
if (!ExecuteBootstrapper(env, node_bootstrapper.ToLocalChecked(), arraysize(node_bootstrapper_args), node_bootstrapper_args, &bootstrapped_node)) { return; } }

 

之后,就是進入事件循環。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM