国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

協(xié)程、線程和執(zhí)行上下文

2019-11-11 00:27:01
字體:
供稿:網(wǎng)友

摘要: 本文介紹協(xié)程、線程及它們執(zhí)行的上下文等概念,同時(shí)給出注意事項(xiàng)。協(xié)程是用戶級(jí)的任務(wù)調(diào)度,線程是內(nèi)核級(jí)的任務(wù)調(diào)度,而任務(wù)調(diào)度過程都涉及到上下文切換(保存與恢復(fù)),本文將從較為深刻的角度來闡述這些概念,及其相互關(guān)系。

協(xié)程和線程

線程在現(xiàn)代的系統(tǒng)里扮演的角色很重要,幾乎一個(gè)現(xiàn)代一點(diǎn)的,稍微復(fù)雜大型一點(diǎn)的程序,往往都會(huì)引入線程,實(shí)現(xiàn)某種意義的并行。線程存在廣泛的支持,從操作系統(tǒng),到編譯器,再到語言的定義與實(shí)現(xiàn)者,他們都在努力讓線程更好用,也有更少的限制。相反協(xié)程的現(xiàn)實(shí)要慘淡很多,在操作系統(tǒng)那里很少有協(xié)程的影子;只有Windows里,存在一個(gè)協(xié)程的實(shí)現(xiàn)——fiber(在那里它被稱為纖程)。

從概念上來說,線程和協(xié)程最大的區(qū)別就是調(diào)度方式不同——線程是被動(dòng)調(diào)度的,協(xié)程是主動(dòng)調(diào)度的。也就是說,線程什么時(shí)候執(zhí)行,什么時(shí)候不執(zhí)行,完全是OS決定,線程是OS的菜,程序員最多只能主動(dòng)讓線程停下來,卻很難讓線程主動(dòng)運(yùn)行起來。相反協(xié)程的執(zhí)行與停止完全由程序員決定,何時(shí)執(zhí)行、何時(shí)停止簡單地調(diào)用一個(gè)協(xié)助方法就可以完成。因?yàn)榫€程是被動(dòng)調(diào)度的,所以線程需要大量同步方法;而協(xié)程是主動(dòng)調(diào)度的,所以協(xié)程之間的同步可以很自然完成——該停該跑——就這簡單直接。

協(xié)程的概念很完美,使用可能也很方便。但是因?yàn)橐恍┪疫€不了解的原因,在C/C++里并沒有廣泛使用協(xié)程庫可用,這是因?yàn)楝F(xiàn)在的OS和編譯器無法很好地支持協(xié)程的實(shí)現(xiàn);這也許是歷史原因,線程在概念上與線程不相矛盾,但它的許多實(shí)現(xiàn)方式限制了實(shí)現(xiàn)通用安全的協(xié)程。在C語言和UNIX草莽朝代,實(shí)現(xiàn)一個(gè)協(xié)程要比實(shí)現(xiàn)一個(gè)函數(shù)(協(xié)程的一種特例)更困難,而對(duì)于當(dāng)時(shí)來說,函數(shù)已經(jīng)完全夠用了,如此協(xié)程被冷淡了。

在用戶層協(xié)程被死死地限制了,可是在linux內(nèi)核里,它卻一個(gè)基本的構(gòu)件——內(nèi)核線程,在更多的時(shí)候,更一個(gè)協(xié)程。當(dāng)然這句話是我自己說,在我很有限的Linux內(nèi)核經(jīng)驗(yàn)上說的,極有可能是錯(cuò)誤的。

執(zhí)行上下文

線程是操作系統(tǒng)實(shí)現(xiàn)的,也是操作系統(tǒng)的調(diào)度單位。我們知道,所謂調(diào)度就是操作系統(tǒng)根據(jù)一些規(guī)則決定在何時(shí)中止一個(gè)線程操作,并在一個(gè)恰當(dāng)?shù)臅r(shí)候再喚醒這個(gè)線程。這里有個(gè)自然的問題,就是操作系統(tǒng)怎么實(shí)現(xiàn)中止與喚醒操作的?其時(shí)停止與喚醒操作都離不開CPU的支持,CPU在硬件上實(shí)現(xiàn)了中斷機(jī)制,OS使用中斷機(jī)制實(shí)現(xiàn)了線程調(diào)度。OS可以告訴CPU,每過100ms(毫秒)或10ms你就調(diào)用一下一段代碼——這就是所謂的時(shí)鐘中斷例程,OS在這一小段代碼里實(shí)現(xiàn)了線程的中止與喚醒。在這段代碼里,OS通常會(huì)做這些事:

保存一下當(dāng)前的狀態(tài),當(dāng)前是哪個(gè)線程在執(zhí)行,當(dāng)前這個(gè)線程執(zhí)行到哪里了,等等——這些狀態(tài)實(shí)際上就是當(dāng)前CPU或CPU-Core里的數(shù)個(gè)特殊寄存器的數(shù)值。我們稱這些狀態(tài)可能放在一個(gè)結(jié)構(gòu)體里,這個(gè)結(jié)構(gòu)體又被稱為上下文(執(zhí)行上下文)。干一些其它的事,如更新系統(tǒng)時(shí)間,看看有沒有什么其它OS需要定時(shí)去做的事,等等。根據(jù)一些規(guī)則(也就是調(diào)度策略),在所有已經(jīng)中止的線程挑選一個(gè),把之前保存起來的狀態(tài)恢復(fù)——實(shí)際上就是把之前保存在結(jié)構(gòu)體的寄存器的值,再加載到相應(yīng)寄存器里。最后,OS執(zhí)行一個(gè)跳轉(zhuǎn)指令,把CPU的執(zhí)行權(quán)限傳遞給剛才挑選的線程,如此這個(gè)線程就從之前停下來的地方接著跑起來了。也就是說,它被喚醒了。

在上面的說明,我們看到一次保存狀態(tài)和一次恢復(fù)狀態(tài),所謂狀態(tài)就是上下文(狀態(tài)),而這個(gè)一次保存和一次恢復(fù)的過程稱為一次上下文切換——大概意思就是說,剛才CPU在干這塊的活,現(xiàn)在它又切換到另一塊地方干活了。

現(xiàn)在我們知道上下文切換,以及OS是如何實(shí)現(xiàn)上下文切換的了,那么有一個(gè)問題,就是程序員能不能在自己的程序里使用與OS相同功能的代碼,在自己的程序進(jìn)行上下文切換?答案是: 完全可以。事實(shí)上,這就是實(shí)現(xiàn)協(xié)程的基本方法。程序在執(zhí)行的時(shí)候是沒有函數(shù)這些概念的,諸如函數(shù)這些概念都上層語言及編譯器實(shí)現(xiàn)的抽象概念,CPU不認(rèn)識(shí)。CPU只認(rèn)識(shí)指令及指令操作的地址。

了解 C++ Boost 庫的人一定知道它最近新加了兩個(gè)庫: context 和 coroutine —— 看這個(gè)名字就知道,前者是實(shí)現(xiàn)了上下文切換的,后者是利用前者實(shí)現(xiàn)了用戶態(tài)協(xié)程的。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 昌图县| 兰溪市| 孟津县| 大荔县| 正安县| 旺苍县| 苏州市| 孟连| 庆元县| 伽师县| 松滋市| 海伦市| 启东市| 富川| 镇赉县| 滦平县| 漾濞| 宜春市| 饶河县| 柳州市| 新乡市| 墨江| 富阳市| 华宁县| 海伦市| 宿松县| 临沧市| 麻江县| 嘉义市| 明星| 稷山县| 汾阳市| 化德县| 根河市| 缙云县| 新绛县| 麻城市| 新邵县| 昌邑市| 江门市| 沾益县|