欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些-創(chuàng)新互聯(lián)

成都創(chuàng)新互聯(lián)公司專注于企業(yè)網(wǎng)絡(luò)營(yíng)銷推廣、網(wǎng)站重做改版、寧陜網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、html5商城網(wǎng)站制作、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為寧陜等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

這篇文章主要介紹Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

  Python虛擬機(jī)框架知識(shí)點(diǎn)講解:


  一、Python字節(jié)碼


  我們知道,Python源代碼在執(zhí)行前,會(huì)先將源代碼編譯為字節(jié)碼序列,Python虛擬機(jī)就根據(jù)這些字節(jié)碼進(jìn)行一系列的操作,從而完成對(duì)Python程序的執(zhí)行。在Python2.5中,一共定義了104條字節(jié)碼指令:


  opcode.h

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  如果我們仔細(xì)看上面的字節(jié)碼指令,會(huì)發(fā)現(xiàn)雖然字節(jié)碼是從0定義到143,但中間有發(fā)生跳躍,比方5直接跳躍到9,13直接跳躍到15,15直接跳躍到18。所以,Python2.5實(shí)際上只定義了104條字節(jié)碼指令


  在Python2.5的104條指令中,有一部分需要參數(shù),另一部分是沒(méi)有參數(shù)的。所有需要參數(shù)的字節(jié)碼指令的編碼都是大于90。Python中提供了專門的宏來(lái)判斷一條字節(jié)碼指令是否需要參數(shù):


  opcode.h

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  我們?cè)赑ython之code對(duì)象與pyc文件(一)、Python之code對(duì)象與pyc文件(二)和Python之code對(duì)象與pyc文件(三)介紹了PyCodeObject對(duì)象,這個(gè)對(duì)象是Python對(duì)源代碼進(jìn)行編譯后在內(nèi)存中產(chǎn)生的靜態(tài)對(duì)象,這個(gè)對(duì)象當(dāng)然也包含了源代碼編譯后的字節(jié)碼,我們可以用Python提供的code對(duì)象解析工具dis對(duì)其進(jìn)行解析

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  最左邊的一列是字節(jié)碼指令在源代碼中所對(duì)應(yīng)的行數(shù),左起第二列是當(dāng)前字節(jié)碼在co_code中的偏移位置,第三列顯示了當(dāng)前字節(jié)碼的指令,第四列是指令的參數(shù),最后一列是計(jì)算后的實(shí)際參數(shù)


  二、Python虛擬機(jī)的運(yùn)行框架


  當(dāng)Python啟動(dòng)后,首先會(huì)進(jìn)行Python運(yùn)行時(shí)環(huán)境的初始化。注意,這里的運(yùn)行時(shí)環(huán)境與之前的章節(jié)《Python之code對(duì)象與pyc文件》中的執(zhí)行環(huán)境是不同的。運(yùn)行時(shí)環(huán)境是一個(gè)全局的概念,而執(zhí)行環(huán)境實(shí)際就是一個(gè)棧幀。是一個(gè)與某個(gè)Code Block對(duì)應(yīng)的概念。而Python虛擬機(jī)的實(shí)現(xiàn),是在一個(gè)函數(shù)中,這里我們列一下源碼,與實(shí)際的源代碼會(huì)做一些刪改:


  ceval.c

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  PyEval_EvalFrameEx首先會(huì)初始化一些變量,其中PyFrameObject對(duì)象中的PyCodeObject對(duì)象包含的重要信息都被照顧到了。當(dāng)然,另一個(gè)重要的動(dòng)作就是初始化了堆棧的棧頂指針stack_pointer,使其指向f->f_stacktop。PyCodeObject對(duì)象中的co_code域中保存著字節(jié)碼指令和字節(jié)碼指令的參數(shù),Python虛擬機(jī)執(zhí)行字節(jié)碼指令序列的過(guò)程就是從頭到尾遍歷整個(gè)co_code、依次執(zhí)行字節(jié)碼指令的過(guò)程。


  在Python虛擬機(jī)中,利用3個(gè)變量來(lái)完成整個(gè)遍歷過(guò)程。co_code實(shí)際上是一個(gè)PyStringObject對(duì)象,而其中的字符數(shù)組才是真正有意義的東西,整個(gè)字節(jié)碼指令序列實(shí)際上在C中就是一個(gè)字符數(shù)組。因此,遍歷過(guò)程中所使用的3個(gè)變量都是char *類型的變量,first_instr永遠(yuǎn)指向字節(jié)碼指令序列的開始位置,next_instr永遠(yuǎn)指向下一條待執(zhí)行的字節(jié)碼指令的位置,f_lasti指向上一條已經(jīng)執(zhí)行過(guò)的字節(jié)碼指令的位置。

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些

       圖1-1展示了3個(gè)變量在遍歷中某時(shí)刻的情景
  
  Python虛擬機(jī)執(zhí)行字節(jié)碼指令的架構(gòu),其實(shí)就是一個(gè)for循環(huán)加上一個(gè)巨大的switch/case結(jié)構(gòu):


  ceval.c

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  上面的代碼只是一個(gè)極度簡(jiǎn)化之后的Python虛擬機(jī)的樣子,完整的代碼實(shí)現(xiàn)在ceval.c文件的PyEval_EvalFrameEx方法中。


  在這個(gè)執(zhí)行架構(gòu)中,對(duì)字節(jié)碼的一步一步地遍歷是通過(guò)幾個(gè)宏來(lái)實(shí)現(xiàn)的:

  ceval.c

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  在對(duì)PyCodeObject對(duì)象分析中我們說(shuō)過(guò),Python字節(jié)碼有的是帶參數(shù)的,有的是沒(méi)帶參數(shù)的,判斷字節(jié)碼是否帶參數(shù)具體參考HAS_ARG這個(gè)宏的實(shí)現(xiàn),對(duì)于不同字節(jié)碼指令,由于存在是否需要指令參數(shù)的區(qū)別,所以next_instr的位移可能是不同的,但無(wú)論如何,next_instr總是指向Python下一條要執(zhí)行的字節(jié)碼。


  Python在獲得了一條字節(jié)碼和其需要的指令參數(shù)后,會(huì)對(duì)字節(jié)碼指令利用switch進(jìn)行判斷,根據(jù)判斷的結(jié)果選擇不同的case語(yǔ)句,每一條字節(jié)碼指令都會(huì)對(duì)應(yīng)一個(gè)case語(yǔ)句。在case語(yǔ)句中,就是Python對(duì)字節(jié)碼指令的實(shí)現(xiàn)。


  在成功執(zhí)行完一條字節(jié)碼指令后,Python的執(zhí)行流程會(huì)跳轉(zhuǎn)到fast_next_opcode處,或者是for循環(huán)處,不管如何,Python接下來(lái)的動(dòng)作都是獲得下一條字節(jié)碼指令和指令參數(shù),完成對(duì)下一條指令的執(zhí)行。如此一條一條地遍歷co_code中包含的所有字節(jié)碼指令,最終完成了對(duì)Python程序的執(zhí)行。


  這里還需要提到一個(gè)變量"why",它指示了退出這個(gè)巨大的for循環(huán)時(shí)Python執(zhí)行引擎的狀態(tài),因?yàn)镻ython執(zhí)行引擎不一定每次執(zhí)行都會(huì)正確無(wú)誤,很有可能在執(zhí)行某條字節(jié)碼時(shí)產(chǎn)生了錯(cuò)誤,這就是我們熟悉的異常——exception。所以在Python退出執(zhí)行引擎的時(shí)候,就需要知道執(zhí)行引擎是因?yàn)槭裁炊Y(jié)束的,是正常結(jié)束呢?還是因?yàn)殄e(cuò)誤的發(fā)生,無(wú)法執(zhí)行下去了?why就承擔(dān)起這一重則變量why的取值范圍在ceval.c中被定義,其實(shí)也是Python結(jié)束字節(jié)碼執(zhí)行時(shí)的狀態(tài):
  ceval.c

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  三、Python運(yùn)行時(shí)環(huán)境初探


  前面我們說(shuō)過(guò),PyFrameObject對(duì)應(yīng)于可執(zhí)行文件在執(zhí)行時(shí)的棧幀,但一個(gè)可執(zhí)行文件要在操作系統(tǒng)中運(yùn)行只有棧幀是不夠的,我們還忽略了兩個(gè)對(duì)于可執(zhí)行文件至關(guān)重要的概念:進(jìn)程和線程。Python在初始化時(shí)會(huì)創(chuàng)建一個(gè)主線程,所以其運(yùn)行環(huán)境中存在一個(gè)主線程。因?yàn)樵诤竺嫫饰鯬ython異常機(jī)制會(huì)利用到Python內(nèi)部的線程模型,因此,我們需要對(duì)Python線程模型有一個(gè)整體概念上的了解。


  以Win32平臺(tái)為例,我們知道,對(duì)于原生Win32可執(zhí)行文件,都會(huì)在一個(gè)進(jìn)程內(nèi)執(zhí)行。進(jìn)程并非是與機(jī)器指令序列相對(duì)應(yīng)的活動(dòng)對(duì)象,這個(gè)可執(zhí)行文件中機(jī)器指令序列對(duì)應(yīng)的活動(dòng)對(duì)象是由線程這個(gè)概念來(lái)進(jìn)行抽象的,而進(jìn)程則是線程的活動(dòng)環(huán)境。


  對(duì)于通常的單線程可執(zhí)行文件,在執(zhí)行時(shí)操作系統(tǒng)會(huì)創(chuàng)建一個(gè)進(jìn)程,在進(jìn)程中,又會(huì)有一個(gè)主線程,而對(duì)于多線程的可執(zhí)行文件,在執(zhí)行時(shí)操作系統(tǒng)會(huì)創(chuàng)建出一個(gè)進(jìn)程和多個(gè)線程,該多個(gè)線程能共享進(jìn)程地址空間中的全局變量,這就自然而然地引出線程同步的問(wèn)題。CPU對(duì)任務(wù)的切換實(shí)際上是在線程間切換,在切換任務(wù)時(shí),CPU需要執(zhí)行線程環(huán)境的保存工作,而在切換至新線程后,需要恢復(fù)該線程的線程環(huán)境。


  前面我們所看到的Python虛擬機(jī)的運(yùn)行框架,實(shí)際上就是對(duì)CPU的抽象,可以看做一個(gè)軟CPU,Python中所有線程都使用這個(gè)軟CPU來(lái)完成計(jì)算工作。真實(shí)機(jī)器的任務(wù)切換機(jī)制對(duì)應(yīng)到Python中,就是使不同的線程輪流使用虛擬機(jī)的機(jī)制。


  CPU切換任務(wù)時(shí)需要保存線程運(yùn)行環(huán)境。對(duì)于Python來(lái)說(shuō),在切換線程之前,同樣需要保存關(guān)于當(dāng)前線程的信息。在Python中,這個(gè)關(guān)于線程狀態(tài)信息的抽象是通過(guò)PyThreadState對(duì)象來(lái)實(shí)現(xiàn)的,一個(gè)線程將擁有一個(gè)PyThreadState對(duì)象。所以從另一種意義來(lái)說(shuō),這個(gè)PyThreadState對(duì)象也可以看成是線程本身的抽象。但實(shí)際上,這兩者是有很大的區(qū)別的,PyThreadState并非是對(duì)線程本身的模擬,因?yàn)镻ython中的線程仍然使用操作系統(tǒng)的原生線程,PyThreadState僅僅是對(duì)線程狀態(tài)的抽象。


  在Win32下,線程是不能獨(dú)立存活的,它需要存活在進(jìn)程的環(huán)境中,而多個(gè)線程可以共享進(jìn)程的一些資源。在Python中也是一樣,如果Python程序中有兩個(gè)線程,都會(huì)進(jìn)行同樣一個(gè)動(dòng)作——import sys,那么這個(gè)sys module應(yīng)該存多少份?是全局共享還是每個(gè)線程但單獨(dú)一個(gè)sys module?如果每個(gè)線程單獨(dú)一份sys module,那么對(duì)Python內(nèi)存的消耗會(huì)非常的驚人,所以在Python中,module都是全局共享的,仿佛這些module都是進(jìn)程中的共享資源一樣,對(duì)于進(jìn)程這個(gè)概念,Python以PyInterpreterState對(duì)象來(lái)實(shí)現(xiàn)。


  在Win32下,通常都會(huì)有多個(gè)進(jìn)程,而Python實(shí)際上也可以由多個(gè)邏輯上的interpreter存在。在通常情況下,Python只有一個(gè)interpreter,這個(gè)interpreter中維護(hù)了一個(gè)或多個(gè)的PyThreadState對(duì)象,與這些PyThreadState對(duì)象對(duì)應(yīng)的線程輪流使用一個(gè)字節(jié)碼執(zhí)行引擎。


  現(xiàn)在,展示一下剛提到的表示進(jìn)程概念的PyInterpreterState對(duì)象和表示線程概念的PyThreadState對(duì)象:


  pystate.h

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  在PyThreadState對(duì)象中,我們看到熟悉的PyFrameObject(_frame)對(duì)象。也就是說(shuō),在每個(gè)PyThreadState對(duì)象中,會(huì)維護(hù)一個(gè)棧幀列表,以與PyThreadState對(duì)象的線程中的函數(shù)調(diào)用機(jī)制對(duì)應(yīng)。在Win32上,情形也是一樣,每個(gè)線程都會(huì)有一個(gè)函數(shù)調(diào)用棧


  當(dāng)Python虛擬機(jī)開始執(zhí)行時(shí),會(huì)將當(dāng)前線程狀態(tài)對(duì)象中的frame設(shè)置為當(dāng)前的執(zhí)行環(huán)境(frame):

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些
  而在建立新的PyFrameObject對(duì)象時(shí),則從當(dāng)前線程的狀態(tài)對(duì)象中取出舊的frame,建立PyFrameObject鏈表:

Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些

以上是“Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

本文題目:Python虛擬機(jī)框架知識(shí)點(diǎn)有哪些-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)鏈接:http://www.chinadenli.net/article46/dodeeg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)網(wǎng)站內(nèi)鏈云服務(wù)器品牌網(wǎng)站設(shè)計(jì)品牌網(wǎng)站建設(shè)品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)