摘要:也就是現(xiàn)代操作系統(tǒng)的虛擬內(nèi)存空間。有在兩個(gè)進(jìn)程之間切換狀態(tài)的時(shí)候,需要把內(nèi)存的映射關(guān)系調(diào)整過來,否則虛擬內(nèi)存的地址是無法對應(yīng)到正確的物理地址的。但是原理是非常類似的。協(xié)程與線程的區(qū)別在于,協(xié)程的是在完全在用戶態(tài),由語言的或者是庫來完成的。
TL;DR
筆者最美好的記憶來自于早年在6502 cpu的cc800上寫匯編的年代, 那個(gè)時(shí)代的計(jì)算機(jī)甚至沒有操作系統(tǒng),也沒有實(shí)模式等保護(hù)機(jī)制。在6502上寫匯編應(yīng)用其實(shí)非常簡單,系統(tǒng)會把bin文件加載到一個(gè)固定的內(nèi)存地址中,cpu會固定地從一個(gè)特定的位置開始執(zhí)行。然后cpu就按照你提供的機(jī)器指令開始一條一條的執(zhí)行。在高級語言中的“函數(shù)調(diào)用”的概念,在匯編里主要體現(xiàn)為兩個(gè)寄存器。寄存器是cpu內(nèi)部臨時(shí)保存數(shù)據(jù)的區(qū)域,相當(dāng)于高級語言里的變量。但是有一個(gè)寄存器是特殊的,它存放了cpu當(dāng)前正在執(zhí)行的指令的內(nèi)存地址(Instruction Register)。一個(gè)高級語言中的函數(shù)一般會被編譯成指令存放在一段連續(xù)的內(nèi)存空間中(data segment)。那么所謂函數(shù)執(zhí)行到了第幾行這樣的信息其實(shí)就是保存在這個(gè)Instruction Register中的。另外一個(gè)很特殊的寄存器是Stack Register,它其中存放的內(nèi)存地址指向的內(nèi)存區(qū)域用于函數(shù)之間傳遞參數(shù)和返回值,以及存放一個(gè)函數(shù)內(nèi)的局部變量。如果不考慮現(xiàn)代計(jì)算機(jī)cpu中各種各樣其他存放中間結(jié)果的寄存器,理論上保存了Instruction Register(執(zhí)行到哪兒了)和Stack Register(堆棧上的變量)就保存了一個(gè)函數(shù)的當(dāng)前執(zhí)行狀態(tài),分別是函數(shù)當(dāng)前執(zhí)行到了哪,以及這個(gè)函數(shù)局部變量所代表的當(dāng)前state。
事實(shí)上,操作系統(tǒng)的幾個(gè)關(guān)鍵切換也是這么來完成的。操作系統(tǒng)提供了兩個(gè)執(zhí)行態(tài),一個(gè)是用戶態(tài),一般我們的代碼都是執(zhí)行在用戶態(tài)的。另外一個(gè)是內(nèi)核態(tài),像驅(qū)動(dòng)程序之類的代碼會用各種方式被加載到操作系統(tǒng)內(nèi)部執(zhí)行在內(nèi)核之中。內(nèi)核態(tài)里的代碼可以完全控制CPU的I/O中斷,從而可以和外部設(shè)備交互。用戶態(tài)的代碼屬于受限代碼,必須把I/O請求通過syscall交由運(yùn)行在內(nèi)核態(tài)的操作系統(tǒng)來完成。當(dāng)一個(gè)cpu的核在執(zhí)行用戶態(tài)代碼時(shí),其寄存器里存放的狀態(tài)是你的應(yīng)用的代碼的狀態(tài),但是應(yīng)用要進(jìn)行I/O操作的時(shí)候,cpu要被切換到內(nèi)核的代碼里去執(zhí)行內(nèi)核態(tài)的代碼。這里就需要進(jìn)行一次context switch,所謂context switch其實(shí)原理不會比把寄存器的值存到內(nèi)存的一個(gè)地方,等回來的時(shí)候再把內(nèi)存中臨時(shí)保存的值加載回寄存器復(fù)雜多少。
操作系統(tǒng)還有一個(gè)需要進(jìn)行context switch的地方,那就是在協(xié)程與協(xié)程之間。操作系統(tǒng)在執(zhí)行一個(gè)ELF或者PE的可執(zhí)行文件的時(shí)候,對于這個(gè)可執(zhí)行文件內(nèi)的匯編代碼來說,整個(gè)內(nèi)存尋址空間是獨(dú)立的。也就是1.exe的執(zhí)行狀態(tài)完全無法感知到2.exe的執(zhí)行狀態(tài)的內(nèi)存。也就是現(xiàn)代操作系統(tǒng)的虛擬內(nèi)存空間。有cpu在兩個(gè)進(jìn)程之間切換狀態(tài)的時(shí)候,需要把內(nèi)存的映射關(guān)系調(diào)整過來,否則虛擬內(nèi)存的地址是無法對應(yīng)到正確的物理地址的。一個(gè)進(jìn)程內(nèi)的兩個(gè)線成切換的時(shí)候,要稍微簡單一些,只需要把當(dāng)前線成正在執(zhí)行的位置和棧做切換就可以了。
無論是操作系統(tǒng)做user/kernel的switch,還是process/process,thread/thread的switch,其實(shí)現(xiàn)方式都是大同小異的。通過把“當(dāng)前執(zhí)行狀態(tài)”這樣的一個(gè)抽象概念落實(shí)為一個(gè)具體的數(shù)據(jù)結(jié)構(gòu)存儲起來,然后指揮cpu在不同的場合加載不同的數(shù)據(jù)恢復(fù)不同的“當(dāng)前執(zhí)行狀態(tài)”。
在高級語言中,一個(gè)函數(shù)正在執(zhí)行的位置以及其狀態(tài),內(nèi)部都可以有一個(gè)抽象的表達(dá)方式。有的高級語言直接被編譯成原生的機(jī)器碼,那么其執(zhí)行狀態(tài)的表述就和操作系統(tǒng)的context switch的context非常類似。有的高級語言自身執(zhí)行在一個(gè)虛擬機(jī)之上,那么其context的表述可能是虛擬機(jī)的instruction register和stack register,而不是80x86這樣原生的機(jī)器的物理寄存器。但是原理是非常類似的。
取決于語言設(shè)計(jì)者的覺悟,有的語言會把這種表達(dá)執(zhí)行狀態(tài)的能力直接提供出來,讓一個(gè)函數(shù)在執(zhí)行過程中可以把當(dāng)前狀態(tài)保存,然后把執(zhí)行權(quán)交給另外一個(gè)函數(shù)執(zhí)行,等那個(gè)函數(shù)放棄執(zhí)行權(quán)回來的時(shí)候再把保存的狀態(tài)恢復(fù)。這也就是所謂的協(xié)程(co-routine)。協(xié)程與線程的區(qū)別在于,協(xié)程的context switch是在完全在用戶態(tài),由語言的runtime或者是庫來完成的。而線程的context switch則是操作系統(tǒng)來完成的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/45309.html
摘要:協(xié)程協(xié)程就是用戶態(tài)的線程要理解是什么是用戶態(tài)的線程,必然就要先理解什么是內(nèi)核態(tài)的線程。記住,不是協(xié)程,而是協(xié)程需要借助的特性來實(shí)現(xiàn)。 協(xié)程 協(xié)程就是用戶態(tài)的線程 要理解是什么是用戶態(tài)的線程,必然就要先理解什么是內(nèi)核態(tài)的線程。 內(nèi)核態(tài)的線程是由操作系統(tǒng)來進(jìn)行調(diào)度的,在切換線程上下文時(shí),要先保存上一個(gè)線程的上下文,然后執(zhí)行下一個(gè)線程,當(dāng)條件滿足時(shí),切換回上一個(gè)線程,并恢復(fù)上下文。 協(xié)程也...
摘要:它避免了上下文切換的額外耗費(fèi),兼顧了多線程的優(yōu)點(diǎn),簡化了高并發(fā)程序的復(fù)雜。而可以理解為一種語言的協(xié)程。線程輕量級進(jìn)程,,是程序執(zhí)行流的最小單元。一個(gè)標(biāo)準(zhǔn)的線程由線程,當(dāng)前指令指針,寄存器集合和堆棧組成。其實(shí)就是或者等語言中的多線程開發(fā)。 grape 全部視頻:https://segmentfault.com/a/11... 原視頻地址:https://biglive.xueersi.c...
摘要:如果僅依靠程序自動(dòng)交出控制的話,那么一些惡意程序?qū)苋菀渍加萌繒r(shí)間而不與其他任務(wù)共享。多個(gè)操作可以在重疊的時(shí)間段內(nèi)進(jìn)行。 PHP下的異步嘗試系列 如果你還不太了解PHP下的生成器,你可以根據(jù)下面目錄翻閱 PHP下的異步嘗試一:初識生成器 PHP下的異步嘗試二:初識協(xié)程 PHP下的異步嘗試三:協(xié)程的PHP版thunkify自動(dòng)執(zhí)行器 PHP下的異步嘗試四:PHP版的Promise ...
摘要:本文先回顧生成器,然后過渡到協(xié)程編程。其作用主要體現(xiàn)在三個(gè)方面數(shù)據(jù)生成生產(chǎn)者,通過返回?cái)?shù)據(jù)數(shù)據(jù)消費(fèi)消費(fèi)者,消費(fèi)傳來的數(shù)據(jù)實(shí)現(xiàn)協(xié)程。解決回調(diào)地獄的方式主要有兩種和協(xié)程。重點(diǎn)應(yīng)當(dāng)關(guān)注控制權(quán)轉(zhuǎn)讓的時(shí)機(jī),以及協(xié)程的運(yùn)作方式。 轉(zhuǎn)載請注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請求 cookie web響應(yīng) sess...
摘要:經(jīng)過半年的沉淀,加上對,和分布式這塊的補(bǔ)齊,終于開始重拾面試信心,再次出征。面試官提示沒有提到線程的有內(nèi)核態(tài)的切換,程只在用戶態(tài)調(diào)度。三面綜合技術(shù)面這面面的是陣腳大亂,面試官采用刨根問底的方式提問,終究是面試經(jīng)驗(yàn)不夠,導(dǎo)致面試的節(jié)奏有點(diǎn)亂。 經(jīng)過半年的沉淀,加上對MySQL,redis和分布式這塊的補(bǔ)齊,終于開始重拾面試信心,再次出征。 鵝廠 面試職位:go后端開發(fā)工程師,接受從Jav...
閱讀 2407·2021-11-16 11:52
閱讀 2359·2021-11-11 16:55
閱讀 789·2021-09-02 15:41
閱讀 3018·2019-08-30 15:54
閱讀 3181·2019-08-30 15:54
閱讀 2286·2019-08-29 15:39
閱讀 1547·2019-08-29 15:18
閱讀 1011·2019-08-29 13:00