一直想着看Nodej源碼,斷斷續續的折騰了一下,但總串不起來,過久不看又忘記。決心天天看一點,特意記錄在這裏,做爲逼迫本身的動力。 html
2019/09/22 1、源碼編譯node
以前在電腦上了下源碼,源碼目錄截圖:linux
編譯經過了,編譯命令:make -j4bootstrap
嘗試修改下源碼文件:lib/http.js,加入一行打印代碼:windows
以後,編譯 make -j4,第一次編譯會花點時間,以後編譯會快不少。編譯以後,在當前目錄下生成out/Release目錄。app
看看修改的代碼是否是有效:dom
cd out/Release
./node
require('http')
能夠看到打印出了required http haha,修改爲功。async
2019/09/23 2、node進程啓動tcp
入口文件:src/node_main.cc,函數
// 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) {
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; }
能夠大概看出流程:
1、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 增長)
2、初始化v8引擎。
3、調用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; } }
以後,就是進入事件循環。