日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

linux 线程_浅谈Linux线程模型

發(fā)布時(shí)間:2025/3/19 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 线程_浅谈Linux线程模型 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Thread Basic

基礎(chǔ)概念

線(xiàn)程是操作系統(tǒng)能夠調(diào)度和執(zhí)行的基本單位,在Linux中也被稱(chēng)之為輕量級(jí)進(jìn)程。從定義中可以看出,線(xiàn)程它是操作系統(tǒng)的概念,在不同的操作系統(tǒng)中的實(shí)現(xiàn)是不同的,不過(guò)今天分享的豬腳是Linux Thread。

對(duì)于Linux操作系統(tǒng)而言,它對(duì)Thread的實(shí)現(xiàn)方式比較特殊。在Linux內(nèi)核中,其實(shí)是沒(méi)有線(xiàn)程的概念的,它把所有的線(xiàn)程當(dāng)做標(biāo)準(zhǔn)的進(jìn)程來(lái)實(shí)現(xiàn),也就是說(shuō)Linux內(nèi)核,并沒(méi)有為線(xiàn)程提供任何特殊的調(diào)度語(yǔ)義,也沒(méi)有為線(xiàn)程實(shí)現(xiàn)特定的數(shù)據(jù)結(jié)構(gòu)。取而代之的是,線(xiàn)程只是一個(gè)與其他進(jìn)程共享某些資源的進(jìn)程。每一個(gè)線(xiàn)程擁有一個(gè)唯一的task_struct結(jié)構(gòu),Linux內(nèi)核它僅僅把線(xiàn)程當(dāng)做一個(gè)正常的進(jìn)程,或者說(shuō)是輕量級(jí)進(jìn)程,LWP(Lightweight processes)。

對(duì)于其他的操作系統(tǒng)而言,比如windows,線(xiàn)程相對(duì)于進(jìn)程,只是一個(gè)提供了更加輕量、快速執(zhí)行單元的抽象概念。對(duì)于Linux而言,線(xiàn)程只是進(jìn)程間共享資源的一種方式,非常輕量。舉個(gè)簡(jiǎn)單例子,假設(shè)有一個(gè)進(jìn)程包含了N個(gè)線(xiàn)程。對(duì)于那些顯示支持線(xiàn)程的操作系統(tǒng)而言,應(yīng)該是存在一個(gè)進(jìn)程描述符,依次輪流指向N個(gè)線(xiàn)程。這個(gè)進(jìn)程描述符指明共享資源,包括內(nèi)存空間和打開(kāi)的文件,然后線(xiàn)程描述它們自己獨(dú)享的資源。相反的是在Linux中,只有N個(gè)進(jìn)程,因此有N個(gè)task_struct數(shù)據(jù)結(jié)構(gòu),只是這些數(shù)據(jù)結(jié)構(gòu)的某些資源項(xiàng)是共享的。

這里再總結(jié)一下,Linux線(xiàn)程是進(jìn)程資源共享的一種方式,而其他操作系統(tǒng),線(xiàn)程則是一種實(shí)現(xiàn)輕量、快速執(zhí)行單元的抽象概念或者實(shí)體。這里再深入的理解一下,Linux中的線(xiàn)程和進(jìn)程的區(qū)別。這也是諸多面試題中,最常見(jiàn)的一個(gè)。

資源共享

Linux線(xiàn)程與進(jìn)程的區(qū)別,主要體現(xiàn)在資源共享、調(diào)度、性能幾個(gè)方面,首先看一下資源共享方面。上面也提到,線(xiàn)程其實(shí)是共享了某一個(gè)進(jìn)程的資源,這些資源包括:

  • 內(nèi)存地址空間
  • 進(jìn)程基礎(chǔ)信息
  • 大部分?jǐn)?shù)據(jù)
  • 打開(kāi)的文件
  • 信號(hào)處理
  • 當(dāng)前工作目錄
  • 用戶(hù)和用戶(hù)組屬性
  • 等等

哪些是線(xiàn)程獨(dú)自擁有的呢?

  • 線(xiàn)程ID
  • 一系列的寄存器
  • 棧的局部變量和返回地址
  • 錯(cuò)誤碼 errno
  • 信號(hào)掩碼
  • 優(yōu)先級(jí)
  • 等等

這里說(shuō)一個(gè)黑科技,線(xiàn)程擁有獨(dú)立的調(diào)用棧,除了棧之外共享了其他所有的段segment。但是由于線(xiàn)程間共享了內(nèi)存,也就是說(shuō)一個(gè)線(xiàn)程,理論上是可以訪(fǎng)問(wèn)到其他線(xiàn)程的調(diào)用棧的,可以用一個(gè)指針變量,去訪(fǎng)問(wèn)其他線(xiàn)程的局部棧幀,以訪(fǎng)問(wèn)其他線(xiàn)程的局部變量。

調(diào)度

說(shuō)到調(diào)度,就得提到進(jìn)程的上下文切換。上下文切換也被稱(chēng)作為進(jìn)程調(diào)度或者任務(wù)切換,簡(jiǎn)單的來(lái)說(shuō)是把CPU從一個(gè)進(jìn)程或者線(xiàn)程切換到另一個(gè)執(zhí)行。概括的來(lái)說(shuō),線(xiàn)程的上下文切換,要比進(jìn)程更加快速,因?yàn)楸举|(zhì)上,線(xiàn)程很多資源都是共享進(jìn)程的,所以切換時(shí),需要保存和切換的項(xiàng)是很少的。

線(xiàn)程上線(xiàn)文切換時(shí),虛擬地址空間是不變的,但是進(jìn)程上下文切換時(shí),是需要重新映射虛擬地址空間。進(jìn)程切換上下文時(shí),進(jìn)出OS內(nèi)核&寄存器切換,是最大的時(shí)間支出。更模糊的代價(jià)是上下文切換時(shí),會(huì)干擾處理器的緩存機(jī)制。當(dāng)上下文切換時(shí),處理器需要重新cache一些內(nèi)存。

這里更大的一個(gè)區(qū)別時(shí),當(dāng)更改虛擬地址空間時(shí),CPU 的 TLB 等也會(huì)被刷新,導(dǎo)致接下來(lái)的內(nèi)存訪(fǎng)問(wèn)更加耗時(shí),所以相對(duì)線(xiàn)程切換來(lái)說(shuō),進(jìn)程的切換耗時(shí)更大。

性能

從性能方面,來(lái)查看一下線(xiàn)程與進(jìn)程的對(duì)比。由于線(xiàn)程更加輕量,導(dǎo)致線(xiàn)程的創(chuàng)建速度、切換速度都要高于進(jìn)程。這里就有一個(gè)疑問(wèn)了,從上面提到的各個(gè)方面來(lái)看,好像線(xiàn)程都要優(yōu)于進(jìn)程,那么有沒(méi)有啥缺點(diǎn)呢?

線(xiàn)程缺點(diǎn)

線(xiàn)程同樣也有缺點(diǎn),最大的缺點(diǎn)是線(xiàn)程的不安全性,缺乏保護(hù)機(jī)制。就是上面提到的黑科技,因?yàn)榫€(xiàn)程間共享數(shù)據(jù),一個(gè)線(xiàn)程可以重寫(xiě)另外一個(gè)線(xiàn)程的堆棧,導(dǎo)致出現(xiàn)一些異常的情況。除此之外,線(xiàn)程還有以下缺點(diǎn):

  • 共享屬性:全局變量是在所有線(xiàn)程間共享的,訪(fǎng)問(wèn)時(shí)是需要同步加鎖。
  • 很多庫(kù)函數(shù)是線(xiàn)程非安全的,多線(xiàn)程編程時(shí),需要注意這一點(diǎn)。
  • 線(xiàn)程的健壯性不強(qiáng),如果一個(gè)線(xiàn)程crash了,那么整個(gè)應(yīng)用程序就跪了。

應(yīng)用場(chǎng)景

上面提到了線(xiàn)程與進(jìn)程的對(duì)比,也提到了線(xiàn)程的優(yōu)點(diǎn)和缺點(diǎn),那么什么情況下適合用線(xiàn)程呢?簡(jiǎn)單的來(lái)說(shuō),計(jì)算密集型的任務(wù),適合于多線(xiàn)程來(lái)處理。因?yàn)橛?jì)算密集型任務(wù),需要耗費(fèi)很多CPU,上下文的切換是非常頻繁的,而線(xiàn)程切換速度是高于進(jìn)程的,所以使用線(xiàn)程是更加適合的。在實(shí)際的編程過(guò)程中,根據(jù)業(yè)務(wù)的場(chǎng)景,再結(jié)合進(jìn)程和線(xiàn)程的優(yōu)缺點(diǎn)對(duì)比,來(lái)決定適合的編程模型。

線(xiàn)程創(chuàng)建

那么Linux中線(xiàn)程是如何創(chuàng)建出來(lái)的呢?上面也提到,在Linux中線(xiàn)程是一種資源共享的方式,可以在創(chuàng)建進(jìn)程的時(shí)候,指定某些資源是從其他進(jìn)程共享的,從而在概念上創(chuàng)建了一個(gè)線(xiàn)程。在Linux中,可以通過(guò)clone系統(tǒng)調(diào)用來(lái)創(chuàng)建一個(gè)進(jìn)程,它的函數(shù)簽名如下:

#include <sched.h> int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);

我們?cè)谑褂胏lone創(chuàng)建進(jìn)程的過(guò)程中,可以指明相應(yīng)的參數(shù),來(lái)決定共享某些資源,比如:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

這個(gè)clone系統(tǒng)調(diào)用的行為類(lèi)似于fork,不過(guò)新創(chuàng)建出來(lái)的進(jìn)程,它的內(nèi)存地址、文件系統(tǒng)資源、打開(kāi)的文件描述符和信號(hào)處理器,都是共享父進(jìn)程的。換句話(huà)說(shuō),這個(gè)新創(chuàng)建出來(lái)的進(jìn)程,也被叫做Linux Thread。從這個(gè)例子中,也可以看出Linux中,線(xiàn)程其實(shí)是進(jìn)程實(shí)現(xiàn)資源共享的一種方式。

內(nèi)核線(xiàn)程

在Linux中,還存在一個(gè)Kernel Thread的概念,也就是內(nèi)核線(xiàn)程。內(nèi)核創(chuàng)建一些內(nèi)核線(xiàn)程來(lái)執(zhí)行一些后臺(tái)任務(wù)。相對(duì)于普通的進(jìn)程,內(nèi)核線(xiàn)程完整的存在于內(nèi)核空間,是沒(méi)有自己的地址空間的,也就是mm指針為空,它的操作僅存在于內(nèi)核態(tài),并且也不會(huì)上下文切換到用戶(hù)態(tài)。不過(guò)內(nèi)核線(xiàn)程和普通進(jìn)程類(lèi)似的是,是可調(diào)度和可搶占的。

同步

由于線(xiàn)程間共享了很多資源,所以在多線(xiàn)程的編程環(huán)境下,為了保障結(jié)果的準(zhǔn)確性和一致性,需要對(duì)共享資源的訪(fǎng)問(wèn)進(jìn)行同步。常見(jiàn)的同步方式,也就是加鎖,以保障操作共享資源時(shí),不會(huì)出錯(cuò)。在Linux中,鎖的種類(lèi)大致有四種:

  • 互斥鎖
  • 讀寫(xiě)鎖
  • 條件變量
  • 自旋鎖
  • 內(nèi)存屏障

有興趣的同學(xué),看看看下這篇文章:http://blog.lecury.cn/2016/02/21/%E5%90%8C%E6%AD%A5%E4%BA%92%E6%96%A5(%E9%94%81).html 。總結(jié)來(lái)說(shuō),鎖的代價(jià)是高昂的,所以在設(shè)計(jì)高并發(fā)、高吞吐的程序時(shí),盡量避免鎖的使用,或者減少鎖的區(qū)間。

常見(jiàn)的多線(xiàn)程編程模式

下面談一下實(shí)際工作中,要如何合理的線(xiàn)程呢?這里我簡(jiǎn)單的提出三種常見(jiàn)的線(xiàn)程模型。

  • leader-follow 模型(主從)
    • 線(xiàn)程與連接對(duì)應(yīng),并發(fā)度等于線(xiàn)程數(shù)。
    • 所有線(xiàn)程經(jīng)歷accept->close整個(gè)過(guò)程。
    • 適用于連接數(shù)少、處理時(shí)間長(zhǎng)、CPU密集型服務(wù)。
  • producer-consumer模型(生產(chǎn)者消費(fèi)者)
    • 主線(xiàn)程用于accept請(qǐng)求,并將fd放置在消費(fèi)隊(duì)列pendingpool中。
    • pendingpool進(jìn)行連接的維護(hù)工作。
    • 多個(gè)worker競(jìng)爭(zhēng)pendingpool的連接。
    • 適用于連接數(shù)多、處理速度快的業(yè)務(wù)。
  • 高并發(fā)索引模型
    • 無(wú)鎖設(shè)計(jì)
    • 將請(qǐng)求或者事務(wù)映射到具體線(xiàn)程處理

踩過(guò)的坑和小技巧

  • 同步
  • 過(guò)載保護(hù)
  • 公平調(diào)度
  • 析構(gòu)出core

更加詳細(xì)的內(nèi)容,請(qǐng)參考知乎Live:

如何理解和應(yīng)用Linux線(xiàn)程模型??www.zhihu.com

感興趣的同學(xué),可以加QQ群: 853832829 一起學(xué)習(xí)~

總結(jié)

以上是生活随笔為你收集整理的linux 线程_浅谈Linux线程模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。