1. 程式人生 > >Nodejs的運行原理-生態篇

Nodejs的運行原理-生態篇

生態圈 返回值 port develop evel 分享 工作 介紹 light

前言

技術分享圖片

這裏是重點:Nodejs 是由v8 engine,libuv和內置模塊組成,可以將v8 engine和 libuv看成一個庫,兩者是以源碼的方式直接編譯執行node中去的。

這是一個廣泛的介紹,後面會詳細介紹Nodejs的生態圈。

V8 engine

V8官方文檔 https://developers.google.com/v8/intro

        #include "include/v8.h"
	#include "include/libplatform/libplatform.h"

	using namespace v8;

	int main(int argc, char* argv[]) {
	// V8初試化.
	V8::InitializeICU();
	Platform* platform = platform::CreateDefaultPlatform();
	V8::InitializePlatform(platform);
	V8::Initialize();

	// 創建isolate.
	Isolate* isolate = Isolate::New();
	{
		Isolate::Scope isolate_scope(isolate);

		// 創建HandleScope.
		HandleScope handle_scope(isolate);

		// 創建context 環境.
		Local<Context> context = Context::New(isolate);
  
		// 引入環境.
		Context::Scope context_scope(context);
  
		// 創建字符串.
		Local<String> source = String::NewFromUtf8(isolate, "‘Hello‘ + ‘, World!‘");
  
		// 編譯字符串.
		Local<Script> script = Script::Compile(source);
  
		// Run,並且獲取返回值.
		Local<Value> result = script->Run();
  
		// 轉換為utf8,並且打印出來.
		String::Utf8Value utf8(result);
		printf("%s\n", *utf8);
	}

	// 關掉v8.
	isolate->Dispose();
	V8::Dispose();
	V8::ShutdownPlatform();
	delete platform;
	return 0;
}

上面代碼展示了一個典型的V8使用例。

1.isolate 代表一個V8實例,各個isolate是獨立的(隔絕的),isolate中的obj無法再另一個isolate中被使用。

2.context 代表執行js代碼的虛擬機,在這個虛擬機中,集成了一些功能,例如math,json,date(),RegExp()等。一個isolate可以同時存在多個context,這些context可以自由切換。如下圖所示。

技術分享圖片

3.在V8 engine中,通過handle訪問存在與heap上的js obj,如local,persistent,eternal,在V8中,有一個handle stack用於管理這些handles,如下圖所示。

技術分享圖片

libuv

libuv主要用於處理事件驅動的異步IO模型,官方文檔 http://nikhilm.github.io/uvbook/

技術分享圖片

libuv通過epoll,kqueue,event ports和IOCP來實現異步network IO。file,dns的操作則依賴於thread pool 來實現,正如上圖所示。

libuv的重點是IO和event loop,loop負責調度callback,運行idle function,執行輪詢等操作。

技術分享圖片

Nodejs

除了V8 engine和libuv ,Nodejs本身也做了很多的工作,它提供了js模塊,c++模塊等核心模塊供開發者使用。

Nodejs 將這些核心js模塊命名為native module,c++模塊命名為builtin module,內建的c++模塊則安放於node源碼lib目錄下。

下圖為native module和builtin module編譯及加載到內存的全過程。

技術分享圖片

當 node test.js 執行時,node_main.cc首先被調用,這一步初始化了V8 engine和libuv執行環境。

uv_run(env->event_loop,UV_RUN_ONCE)用於啟動libuv event loop,而我們的js代碼則會被傳遞到creatEnvironment(),最後交由V8處理。

查看Node.cc代碼,可以看到一些函數與V8交互的工作,例如context,handle等的創建。

在js中,類似基於prototype繼承的方式來實現的,通過V8提供的c++ API來完成這些操作。

Nodejs的運行原理-生態篇