一方面、線程的分類
線程的實(shí)現(xiàn)可以分為兩大類:用戶級(jí)線程和內(nèi)核級(jí)線程。
1.用戶級(jí)線程
在一個(gè)純粹的用戶級(jí)線程軟件中参滴,有關(guān)線程管理的所有工作都由應(yīng)用程序完成车荔,內(nèi)核意識(shí)不到線程的存在。任何應(yīng)用程序都可以通過使用線程庫被設(shè)計(jì)成多線程程序辣辫。線程庫是用于用戶級(jí)線程管理的一個(gè)例程包旦事,它包含用于創(chuàng)建和銷毀線程的代碼、在線程間傳遞消息和數(shù)據(jù)的代碼络它、調(diào)度線程執(zhí)行的代碼族檬、以及保存和恢復(fù)線程上下文的代碼。在默認(rèn)情況下化戳,應(yīng)用程序從單線程開始单料,并在該線程中開始運(yùn)行。該應(yīng)用程序及其線程被分配給一個(gè)由內(nèi)核管理的進(jìn)程点楼。在應(yīng)用程序正在運(yùn)行(進(jìn)程處于運(yùn)行態(tài))的任何時(shí)刻扫尖,應(yīng)用程序都可以派生一個(gè)在相同進(jìn)程中運(yùn)行的新線程(派生線程是通過調(diào)用線程庫中的派生例程完成的,通過過程調(diào)用掠廓,控制權(quán)被傳遞給派生例程)换怖。線程庫為新線程創(chuàng)建一個(gè)數(shù)據(jù)結(jié)構(gòu),然后使用某種調(diào)度算法蟀瞧,把控制權(quán)傳遞給該進(jìn)程中處于就緒態(tài)的一個(gè)線程沉颂。當(dāng)控制權(quán)被傳遞給線程庫時(shí),需要保存當(dāng)前線程的上下文悦污,然后當(dāng)控制權(quán)從線程庫中傳遞給一個(gè)線程時(shí)铸屉,將恢復(fù)哪個(gè)線程的上下文。上下文實(shí)際上包括用戶寄存器的內(nèi)容切端、程序計(jì)數(shù)器和棧指針
在前一段描述的所有活動(dòng)都發(fā)生在用戶空間中彻坛,并且發(fā)生在一個(gè)進(jìn)程內(nèi),而內(nèi)核并不知道這些活動(dòng)。內(nèi)核繼續(xù)以進(jìn)程為單位進(jìn)行調(diào)度昌屉,并且給該進(jìn)程指定一個(gè)執(zhí)行狀態(tài)钙蒙。
使用用戶級(jí)線程而不是內(nèi)核線程有很多優(yōu)點(diǎn):
1、由于所有線程管理數(shù)據(jù)結(jié)構(gòu)都在一個(gè)進(jìn)程的用戶地址空間中间驮,線程切換不需要內(nèi)核態(tài)特權(quán)躬厌;
2、調(diào)度可以是應(yīng)用程序相關(guān)的竞帽,可以做到為應(yīng)用程序量身定做調(diào)度算法而不擾亂底層的操作系統(tǒng)調(diào)度程序烤咧;
3、用戶級(jí)線程可以在任何操作系統(tǒng)中運(yùn)行抢呆,線程庫是一組供所有應(yīng)用程序共享的應(yīng)用程序級(jí)別的函數(shù)。
使用用戶級(jí)線程而不是內(nèi)核線程有兩個(gè)明顯的缺點(diǎn):
1笛谦、當(dāng)用戶級(jí)線程執(zhí)行一個(gè)會(huì)引起阻塞的系統(tǒng)調(diào)用時(shí)抱虐,不僅這個(gè)線程會(huì)被阻塞,進(jìn)程中的所有線程都會(huì)被阻塞饥脑;
2恳邀、在純粹的用戶級(jí)線程策略中,多線程應(yīng)用程序不能利用多處理技術(shù)灶轰,內(nèi)核一次只把一個(gè)進(jìn)程分配給一個(gè)處理器谣沸,因此一次進(jìn)程中只有一個(gè)線程可以執(zhí)行。
2.內(nèi)核級(jí)線程
在一個(gè)純粹的內(nèi)核級(jí)線程軟件中笋颤,有關(guān)線程管理的所有工作都是由內(nèi)核完成的乳附,應(yīng)用程序部分沒有進(jìn)行線程管理的代碼,只有一個(gè)到內(nèi)核線程設(shè)施的應(yīng)用程序編程接口(API)伴澄。Windows 是這種方法的一個(gè)例子赋除。
內(nèi)核為進(jìn)程及其內(nèi)部的每個(gè)線程維護(hù)上下文信息。調(diào)度是由內(nèi)核基于線程完成的非凌。該方法克服了用戶級(jí)線程方法的兩個(gè)基本缺陷(優(yōu)點(diǎn):):
首先:內(nèi)核可以同時(shí)把同一個(gè)進(jìn)程中的多個(gè)線程調(diào)度到多個(gè)處理器中举农;
再者:如果進(jìn)程中的一個(gè)線程被阻塞,內(nèi)核可以調(diào)度同一個(gè)進(jìn)程中的另一個(gè)線程敞嗡;
另外:內(nèi)核例程自身也是可以使用多線程的颁糟。
缺點(diǎn):把控制從一個(gè)線程傳送到同一個(gè)進(jìn)程內(nèi)的另一個(gè)線程時(shí),需要到內(nèi)核的狀態(tài)轉(zhuǎn)換
二喉悴、Windows線程
Windows 使用兩類與進(jìn)程相關(guān)的對(duì)象:進(jìn)程和線程棱貌。
進(jìn)程是對(duì)應(yīng)一個(gè)擁有內(nèi)存、打開的文件等資源的用戶作業(yè)或應(yīng)用程序的實(shí)體粥惧。線程是順序執(zhí)行的一個(gè)科分派的工作單元键畴,并且它是可中斷的,因此,處理器可以切換到另一個(gè)線程起惕。一個(gè) Windows 進(jìn)程必須至少包含一個(gè)執(zhí)行線程涡贱,該線程可能會(huì)創(chuàng)建別的線程。在多處理器系統(tǒng)中惹想,同一個(gè)進(jìn)程的多個(gè)線程可以并行的執(zhí)行问词。
由于不同進(jìn)程中的線程可能并非執(zhí)行,因而 Windows 支持進(jìn)程間的并發(fā)性嘀粱。此外激挪,同一個(gè)進(jìn)程中的多個(gè)線程可以分配給不同的處理器并且同時(shí)執(zhí)行。一個(gè)含有多線程的進(jìn)程在實(shí)現(xiàn)并發(fā)時(shí)锋叨,不需要使用多進(jìn)程的開銷垄分。同一個(gè)進(jìn)程中的線程可以通過他們的公共地址空間交換信息,并訪問進(jìn)程中的共享資源娃磺,不同進(jìn)程中的線程可以通過在兩個(gè)進(jìn)程間建立的共享內(nèi)存交換信息
三薄湿、Linux的進(jìn)程和線程管理
Linux 中的進(jìn)程或任務(wù)由一個(gè) task_struct 數(shù)據(jù)結(jié)構(gòu)表示。
傳統(tǒng)的 UNIX 系統(tǒng)支持每個(gè)執(zhí)行的進(jìn)程中只有一個(gè)單獨(dú)的一個(gè)線程偷卧,但現(xiàn)代典型的 UNIX 系統(tǒng)支持一個(gè)進(jìn)程中含有多個(gè) 內(nèi)核級(jí)線程豺瘤。
** Linux 提供一種不區(qū)分進(jìn)程和線程的解決方案**。用戶級(jí)線程被映射到內(nèi)核級(jí)進(jìn)程上听诸,組成一個(gè)用戶級(jí)進(jìn)程的多個(gè)用戶級(jí)線程被映射到共享同一個(gè)組 ID 的多個(gè) Linux 內(nèi)核級(jí)進(jìn)程上坐求。這使得這些進(jìn)程可以共享文件和內(nèi)存等資源,使得同一組中的進(jìn)程調(diào)度切換時(shí)不需要切換上下文晌梨。
當(dāng)兩個(gè)進(jìn)程共享相同的虛存時(shí)桥嗤,它們可以被當(dāng)做是一個(gè)進(jìn)程中的線程。
當(dāng) Linux 內(nèi)核執(zhí)行從一個(gè)進(jìn)程到另一個(gè)進(jìn)程的切換時(shí)派任,它將堅(jiān)持當(dāng)前進(jìn)程的頁目錄地址是否和將被調(diào)度的進(jìn)程相同砸逊。如果相同,那么它們共享同一個(gè)地址空間掌逛,所以此時(shí)上下文切換僅僅是從代碼的一處跳轉(zhuǎn)到代碼的另一處师逸。
雖然屬于同一進(jìn)程組的被克隆的進(jìn)程共享同一內(nèi)存空間,但它們不能共享同一個(gè)用戶棧豆混。
四篓像、總結(jié)
用戶級(jí)線程對(duì)操作系統(tǒng)是未知的,它們由一個(gè)在進(jìn)程的用戶空間中運(yùn)行的線程庫創(chuàng)建并管理皿伺。用戶線程是非常高效的员辩,因?yàn)閺囊粋€(gè)線程切換到另一個(gè)線程不需要進(jìn)行狀態(tài)切換,但是鸵鸥,一個(gè)進(jìn)程中一次只有一個(gè)用戶級(jí)線程可以執(zhí)行奠滑,如果一個(gè)線程發(fā)生阻塞丹皱,整個(gè)進(jìn)程都會(huì)被阻塞。
進(jìn)程內(nèi)包含的內(nèi)核級(jí)線程是由內(nèi)核維護(hù)的宋税。由于內(nèi)核認(rèn)識(shí)它們摊崭,因而同一個(gè)進(jìn)程中的多個(gè)線程可以再多個(gè)處理器上并行執(zhí)行,一個(gè)線程的阻塞不會(huì)阻塞整個(gè)進(jìn)程杰赛,但當(dāng)從一個(gè)線程切換到另一個(gè)線程時(shí)就會(huì)需要進(jìn)行模式切換呢簸。