溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python虛擬機框架知識點有哪些

發布時間:2021-10-28 10:32:47 來源:億速云 閱讀:208 作者:小新 欄目:編程語言

這篇文章主要介紹Python虛擬機框架知識點有哪些,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

  Python虛擬機框架知識點講解:


  一、Python字節碼


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


  opcode.h

Python虛擬機框架知識點有哪些
  如果我們仔細看上面的字節碼指令,會發現雖然字節碼是從0定義到143,但中間有發生跳躍,比方5直接跳躍到9,13直接跳躍到15,15直接跳躍到18。所以,Python2.5實際上只定義了104條字節碼指令


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


  opcode.h

Python虛擬機框架知識點有哪些
  我們在Python之code對象與pyc文件(一)、Python之code對象與pyc文件(二)和Python之code對象與pyc文件(三)介紹了PyCodeObject對象,這個對象是Python對源代碼進行編譯后在內存中產生的靜態對象,這個對象當然也包含了源代碼編譯后的字節碼,我們可以用Python提供的code對象解析工具dis對其進行解析

Python虛擬機框架知識點有哪些
  最左邊的一列是字節碼指令在源代碼中所對應的行數,左起第二列是當前字節碼在co_code中的偏移位置,第三列顯示了當前字節碼的指令,第四列是指令的參數,最后一列是計算后的實際參數


  二、Python虛擬機的運行框架


  當Python啟動后,首先會進行Python運行時環境的初始化。注意,這里的運行時環境與之前的章節《Python之code對象與pyc文件》中的執行環境是不同的。運行時環境是一個全局的概念,而執行環境實際就是一個棧幀。是一個與某個Code Block對應的概念。而Python虛擬機的實現,是在一個函數中,這里我們列一下源碼,與實際的源代碼會做一些刪改:


  ceval.c

Python虛擬機框架知識點有哪些
  PyEval_EvalFrameEx首先會初始化一些變量,其中PyFrameObject對象中的PyCodeObject對象包含的重要信息都被照顧到了。當然,另一個重要的動作就是初始化了堆棧的棧頂指針stack_pointer,使其指向f->f_stacktop。PyCodeObject對象中的co_code域中保存著字節碼指令和字節碼指令的參數,Python虛擬機執行字節碼指令序列的過程就是從頭到尾遍歷整個co_code、依次執行字節碼指令的過程。


  在Python虛擬機中,利用3個變量來完成整個遍歷過程。co_code實際上是一個PyStringObject對象,而其中的字符數組才是真正有意義的東西,整個字節碼指令序列實際上在C中就是一個字符數組。因此,遍歷過程中所使用的3個變量都是char *類型的變量,first_instr永遠指向字節碼指令序列的開始位置,next_instr永遠指向下一條待執行的字節碼指令的位置,f_lasti指向上一條已經執行過的字節碼指令的位置。

Python虛擬機框架知識點有哪些

       圖1-1展示了3個變量在遍歷中某時刻的情景
  
  Python虛擬機執行字節碼指令的架構,其實就是一個for循環加上一個巨大的switch/case結構:


  ceval.c

Python虛擬機框架知識點有哪些
  上面的代碼只是一個極度簡化之后的Python虛擬機的樣子,完整的代碼實現在ceval.c文件的PyEval_EvalFrameEx方法中。


  在這個執行架構中,對字節碼的一步一步地遍歷是通過幾個宏來實現的:

  ceval.c

Python虛擬機框架知識點有哪些
  在對PyCodeObject對象分析中我們說過,Python字節碼有的是帶參數的,有的是沒帶參數的,判斷字節碼是否帶參數具體參考HAS_ARG這個宏的實現,對于不同字節碼指令,由于存在是否需要指令參數的區別,所以next_instr的位移可能是不同的,但無論如何,next_instr總是指向Python下一條要執行的字節碼。


  Python在獲得了一條字節碼和其需要的指令參數后,會對字節碼指令利用switch進行判斷,根據判斷的結果選擇不同的case語句,每一條字節碼指令都會對應一個case語句。在case語句中,就是Python對字節碼指令的實現。


  在成功執行完一條字節碼指令后,Python的執行流程會跳轉到fast_next_opcode處,或者是for循環處,不管如何,Python接下來的動作都是獲得下一條字節碼指令和指令參數,完成對下一條指令的執行。如此一條一條地遍歷co_code中包含的所有字節碼指令,最終完成了對Python程序的執行。


  這里還需要提到一個變量"why",它指示了退出這個巨大的for循環時Python執行引擎的狀態,因為Python執行引擎不一定每次執行都會正確無誤,很有可能在執行某條字節碼時產生了錯誤,這就是我們熟悉的異常——exception。所以在Python退出執行引擎的時候,就需要知道執行引擎是因為什么而結束的,是正常結束呢?還是因為錯誤的發生,無法執行下去了?why就承擔起這一重則變量why的取值范圍在ceval.c中被定義,其實也是Python結束字節碼執行時的狀態:
  ceval.c

Python虛擬機框架知識點有哪些
  三、Python運行時環境初探


  前面我們說過,PyFrameObject對應于可執行文件在執行時的棧幀,但一個可執行文件要在操作系統中運行只有棧幀是不夠的,我們還忽略了兩個對于可執行文件至關重要的概念:進程和線程。Python在初始化時會創建一個主線程,所以其運行環境中存在一個主線程。因為在后面剖析Python異常機制會利用到Python內部的線程模型,因此,我們需要對Python線程模型有一個整體概念上的了解。


  以Win32平臺為例,我們知道,對于原生Win32可執行文件,都會在一個進程內執行。進程并非是與機器指令序列相對應的活動對象,這個可執行文件中機器指令序列對應的活動對象是由線程這個概念來進行抽象的,而進程則是線程的活動環境。


  對于通常的單線程可執行文件,在執行時操作系統會創建一個進程,在進程中,又會有一個主線程,而對于多線程的可執行文件,在執行時操作系統會創建出一個進程和多個線程,該多個線程能共享進程地址空間中的全局變量,這就自然而然地引出線程同步的問題。CPU對任務的切換實際上是在線程間切換,在切換任務時,CPU需要執行線程環境的保存工作,而在切換至新線程后,需要恢復該線程的線程環境。


  前面我們所看到的Python虛擬機的運行框架,實際上就是對CPU的抽象,可以看做一個軟CPU,Python中所有線程都使用這個軟CPU來完成計算工作。真實機器的任務切換機制對應到Python中,就是使不同的線程輪流使用虛擬機的機制。


  CPU切換任務時需要保存線程運行環境。對于Python來說,在切換線程之前,同樣需要保存關于當前線程的信息。在Python中,這個關于線程狀態信息的抽象是通過PyThreadState對象來實現的,一個線程將擁有一個PyThreadState對象。所以從另一種意義來說,這個PyThreadState對象也可以看成是線程本身的抽象。但實際上,這兩者是有很大的區別的,PyThreadState并非是對線程本身的模擬,因為Python中的線程仍然使用操作系統的原生線程,PyThreadState僅僅是對線程狀態的抽象。


  在Win32下,線程是不能獨立存活的,它需要存活在進程的環境中,而多個線程可以共享進程的一些資源。在Python中也是一樣,如果Python程序中有兩個線程,都會進行同樣一個動作——import sys,那么這個sys module應該存多少份?是全局共享還是每個線程但單獨一個sys module?如果每個線程單獨一份sys module,那么對Python內存的消耗會非常的驚人,所以在Python中,module都是全局共享的,仿佛這些module都是進程中的共享資源一樣,對于進程這個概念,Python以PyInterpreterState對象來實現。


  在Win32下,通常都會有多個進程,而Python實際上也可以由多個邏輯上的interpreter存在。在通常情況下,Python只有一個interpreter,這個interpreter中維護了一個或多個的PyThreadState對象,與這些PyThreadState對象對應的線程輪流使用一個字節碼執行引擎。


  現在,展示一下剛提到的表示進程概念的PyInterpreterState對象和表示線程概念的PyThreadState對象:


  pystate.h

Python虛擬機框架知識點有哪些Python虛擬機框架知識點有哪些
  在PyThreadState對象中,我們看到熟悉的PyFrameObject(_frame)對象。也就是說,在每個PyThreadState對象中,會維護一個棧幀列表,以與PyThreadState對象的線程中的函數調用機制對應。在Win32上,情形也是一樣,每個線程都會有一個函數調用棧


  當Python虛擬機開始執行時,會將當前線程狀態對象中的frame設置為當前的執行環境(frame):

Python虛擬機框架知識點有哪些
  而在建立新的PyFrameObject對象時,則從當前線程的狀態對象中取出舊的frame,建立PyFrameObject鏈表:

Python虛擬機框架知識點有哪些

以上是“Python虛擬機框架知識點有哪些”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女