日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

node源码详解(五)

發(fā)布時間:2023/12/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 node源码详解(五) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?本作品采用知識共享署名 4.0 國際許可協(xié)議進行許可。轉(zhuǎn)載保留聲明頭部與原文鏈接https://luzeshu.com/blog/nodesource5?
本博客同步在https://cnodejs.org/topic/56ed6735b705742136388fa6?
本博客同步在http://www.cnblogs.com/papertree/p/5295344.html


  在上一篇博客(詳解四)講了 C++通過v8的Object類和FunctionTemplate類,創(chuàng)建對象、方法,設(shè)置屬性、原型方法等,提供給運行時的 js代碼調(diào)用。

  那么這些C++實現(xiàn)的process對象、TCP類是否都在程序啟動的時候就創(chuàng)建到 js的執(zhí)行環(huán)境(context)呢?

  不全是。process對象是(見5.2節(jié)),但 TCP類等C++內(nèi)建模塊不是(見5.3節(jié))。  

5.1 在main函數(shù)啟動之前 —— C++內(nèi)建模塊的注冊

  看一下C++內(nèi)建模塊的實現(xiàn)方法:

圖5-1-1

  我們看到最后一行的NODE_MODULE_CONTEXT_AWARE_BUILTIN,通過這個方式來導(dǎo)出一個C++內(nèi)建模塊,這行代碼實現(xiàn)了什么?

5.1.1?NODE_MODULE_CONTEXT_AWARE_BUILTIN 宏

  看下這個宏的實現(xiàn),在src/node.h文件:

圖5-1-2

5.1.2 NODE_C_CTOR宏與__attribute__((constructor))聲明 —— 在main函數(shù)前注冊

  看到NODE_C_CTOR這個宏的作用時給傳進來的函數(shù)加上這么一個聲明,這是gcc的一個函數(shù)屬性聲明。

  來自gcc文檔的說明:(地址:https://gcc.gnu.org/onlnedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes)

    [?The?constructor?attribute causes the function to be called automatically before execution enters?main (). ]

    ?[筆者譯:constructor屬性導(dǎo)致該函數(shù)在程序進入main函數(shù)之前被執(zhí)行]  

  注:上面的 “.CRT$XCU”是微軟的編譯器實現(xiàn)類似功能的方法。

5.1.3 node_module_register函數(shù) 與 node::node_module結(jié)構(gòu)體的鏈表modlist_builtin

  通過圖5-1-2,可以知道通過NODE_MODULE_CONTEXT_AWARE_BUILTIN( tcp_wrap, TCPWrap::Initialize )宏去注冊一個C++內(nèi)建模塊時,過程如下:

  1. 把 tcp_wrap(modname)和 Initilize函數(shù)(regfunc)封裝成一個node_module類型的結(jié)構(gòu)體 _module

  2.?調(diào)用node_module_register(&_module) 函數(shù)進行注冊。

圖5-1-3

  可以看到這個函數(shù)把傳進來的m插入到內(nèi)建模塊的鏈表modlist_builtin。

?

5.1.4 總結(jié)

  通過5.1節(jié),我們知道tcp_wrap.cc里面實現(xiàn)的C++內(nèi)建模塊,在main函數(shù)啟動之前把該內(nèi)建模塊的初始化函數(shù) TCPWrap::Initialize()保存到一個全局的靜態(tài)鏈表modlist_builtin。

  那么這些內(nèi)建模塊的Initialize()什么時候執(zhí)行呢?里面可是創(chuàng)建了TCP類對應(yīng)的FunctionTemplate呢,在創(chuàng)建對應(yīng)的FunctionTemplate對象之前,V8的context里頭,js代碼還是沒得直接使用new TCP()呢。


5.2 process.binding —— C++內(nèi)建模塊的初始化與緩存

  既然C++內(nèi)建模塊只是保存初始化函數(shù)到鏈表,而不真正創(chuàng)建一個js可以使用的函數(shù)對象(TCP類)到v8的上下文(context),那么初始化這個步驟明顯要交給 js代碼來控制了。

  通過process.binding('tcp_wrap') 來引入C++內(nèi)建模塊創(chuàng)建的對象,如果第一次binding這個內(nèi)建模塊,那么就會調(diào)用Initialize函數(shù)。

  那么你可能會問,C++內(nèi)建模塊就需要 js里面調(diào)用process.binding()來引入,那process對象也是C++提供的v8::Object類型的對象,為什么可以直接使用process.binding()呢?

  因為內(nèi)建模塊并不是你js代碼一定會用到的,所以通過保存TCPWrap::Initialize()的方式,等到要用到時再通過process.binding()初始化。你要一開始就執(zhí)行初始化函數(shù),也是可以創(chuàng)建對應(yīng)的FunctionTemplate對象到v8上下文的。

  而process這個對象在main函數(shù)啟動之后、執(zhí)行node.js之前就創(chuàng)建了,那么js代碼運行的上下文(context)里面就可以直接用了。具體代碼見5.3節(jié)。

  來看一下process.binding()的過程:

  [注:C++設(shè)置給process對象的binding方法是下面的Binding()函數(shù)]

圖5-2-1

  1. Binding()函數(shù)通過要binding的模塊名,調(diào)用get_builtin_module(),從5.1.3中提到的內(nèi)建模塊鏈表modlist_buildin去獲取node::node_module結(jié)構(gòu)體對象

  2. node_module對象里面的nm_context_register_func字段保存著對應(yīng)的初始化函數(shù)(即5.1.3中保存的TCPWrap::Initialize),圖中第2320行可以看出binding的時候執(zhí)行了初始化函數(shù)。

  3. 最后把exports當成process.binding()的返回值。exports哪里被賦值呢?注意到nm_context_register_func其實是tcp_wrap.cc里面的TCPWrap::Initialize()函數(shù),回去圖5-1-1看看這個函數(shù),就會發(fā)現(xiàn)哦原來就是target。

?


?

5.3 process對象的初始化

  在3.1.2節(jié)中講到這么一個流程:

    main() ->?Start() -> StartNodeInstance() -> LoadEnviroment()

  在LoadEnvrionment()里面去執(zhí)行node.js文件,并把process對象傳進去。

5.3.1 process初始化(js部分)

  在LoadEnvrionment()執(zhí)行node.js文件,并傳process進去的時候,process.nextTick()這些函數(shù)是在node.js里面初始化的。

5.3.1 process初始化(C++部分)

  在main() -> Start() -> StartNodeInstance() 這里,執(zhí)行LoadEnvironment()之前,先調(diào)用了CreateEnvironment()。

  在CreateEnvironment()里面創(chuàng)建process對象,并且初始化C++部分的函數(shù)。看代碼:

圖5-3-1

  1. 創(chuàng)建v8::Object process_object 在 CreateEnvironment()里面。

  2. 給process.binding等賦值在SetupProcessObject()里面。

?

轉(zhuǎn)載于:https://www.cnblogs.com/xieweikai/p/6817671.html

總結(jié)

以上是生活随笔為你收集整理的node源码详解(五)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。