線程(下)【Linux操作系統】

文章目錄

  • 線程控制
    • 線程共享進程地址空間中的所有數據
    • 線程會瓜分進程的時間片
    • 線程相關庫函數
      • 庫函數:pthread_create
      • 庫函數:pthread_self
      • 庫函數:pthread_join
      • 庫函數:pthread_exit
      • 庫函數:pthread_cancel[盡量少用]
      • 庫函數:pthread_detach
    • 為什么Linux線程相關的函數是庫函數,而不是系統調用?
    • 線程的狀態和回收
    • 線程終止
    • 線程分離
  • 線程庫的理解
    • 線程id
    • 線程TCB的存放和內容
      • TCB的存儲
      • TCB中的內容
    • 線程的棧
    • 線程局部存儲

線程控制

線程共享進程地址空間中的所有數據

全局區,代碼區,堆區,共享區,棧區都是共享的
沒錯棧區也是共享的
只要線程a能拿到線程b函數中的棧區變量的地址,就可以對它進行修改和訪問
而且修改之后,線程b看到的也是改變了之后的【但是強烈不建議這么做



線程會瓜分進程的時間片

即:
一個進程的時間片是10ns
它一共有5個線程,那么每個線程的時間片就是2ns

為什么呢?
操作系統進行調度時,是以線程為單位的
而且承擔資源分配的基本實體是進程,進程是資源的容器,線程瓜分進程資源,而時間片也是資源!!!
所以,必須給每個線程分時間片,這樣操作系統調度線程時,才知道線程什么時候時間片耗盡

而且:
如果線程的時間片和它所屬的進程一樣長,那么一個進程就可以通過創建更多線程,來延長自己占用CPU的時間
這顯然對其他進程不公平
這和分時操作系統的公平調度理念不符



線程相關庫函數

庫函數:pthread_create

  • 頭文件:pthread.h

  • 返回值:int
    ①成功,就返回0
    ②失敗,就返回錯誤碼

  • 參數表:

    • pthread_t *thread:輸出型參數,用于獲取線程tid,本質也是一個整型

    • const pthread_attr_t *attr:線程屬性

    • (void*)(*p)(void*):指向給這個線程分配的函數的函數指針

    • void*arg:傳給分配給線程的函數的參數
      為什么是void * 類型?
      就是為了支持接收任意類型的參數,變量,數組,對象都可以傳遞過去
      這樣就可以一次傳遞多個信息,也可以更好地支持C和C++混合編寫
      我們可以定義一個任務類,里面存儲一些基本信息和分配給這個新線程的任務函數
      即設計一個任務類,里面的成員變量就是任務函數,以及任務函數對應的參

  • 作用:創建一個線程


庫函數:pthread_self

  • 頭文件:pthread.h

  • 返回值:pthread_t
    ①成功,該線程的tid
    ②失敗,就返回-1

  • 作用:獲取唯一標識一個線程的tid


庫函數:pthread_join

  • 頭文件:pthread.h

  • 返回值:int
    ①成功,0
    ②失敗,就返回錯誤碼

  • 參數表:

    • pthread_t thread:要等待的線程的tid

    • void**retval因為分配給新線程的函數的返回值為void*類型的,所以以輸出型參數的方式獲取這個返回值就得是void**類型的

  • 注意:
    pthread_join是阻塞等待的從線程的
    一般是主線程等待從線程


庫函數:pthread_exit

  • 頭文件:pthread.h

  • 返回值:void

  • 參數表:
    void*retval:線程的退出信息

  • 作用:讓調用這個函數的線程退出


庫函數:pthread_cancel[盡量少用]

  • 頭文件:pthread.h

  • 返回值:int
    ①成功,0
    ②失敗,就返回錯誤碼

  • 參數表:
    pthread_t thread:要取消的線程的tid

  • 注意:

    • ①一個線程能被取消的前提是,這個線程已經啟動了
    • ②被取消的線程也必須被回收(不然會內存泄露),而且退出碼必定是-1

庫函數:pthread_detach

  • 頭文件:pthread.h

  • 參數表:
    pthread_t thread:要設置成要把被等待狀態設置成detach的線程的tid

  • 作用:
    把指定線程的被等待狀態設置成detach



為什么Linux線程相關的函數是庫函數,而不是系統調用?

因為在Linux中沒有給線程先描述再組織
Linux內核中的線程是使用LWP模擬實現的
所以
Linux內核就只給我們提供了創建LWP的系統調用接口(即系統調用clone)操作線程的各種系統調用通通沒有

用戶不愿意直接去使用創建LWP的系統調用,因為使用這個系統調用還得去了解Linux的LWP等相關知識,成本太高了
所以
Linux就讓庫封裝了LWP相關的系統調用得到了給用戶提供了包括線程的各種操作的的庫[庫的名字就叫pthread]
封裝成庫之后,用戶就只需要知道線程的相關概念就可以輕松使用庫函數了

所以
Linux中,如果使用了線程相關的函數,那么編譯時都要鏈接pthread動態庫,pthread是Linux實現的自帶的庫,是原生線程庫
所以:
其他任何語言想要在Linux平臺上支持線程,就必須封裝Linux的pthread庫



線程的狀態和回收

Linux中的線程就是用LWP(task_struct)模擬實現的
所以一個線程對應一個PCB
而PCB里面就存儲了狀態信息
所以線程的狀態管理,完全可以復用進程的狀態管理

從線程也需要被主線程等待和回收(使用pthread_join)
為什么?

  • ①因為線程的退出信息,在線程庫中它自己的TCB中維護著,而TCB關聯內核的LWP的生命周期

  • ②因為主線程也要知道其他線程把任務執行地怎么樣
    所以如果不等待,即使線程退出了,操作系統也不敢釋放它的LWP,就會出現與進程類似的僵尸問題



線程終止

會讓線程終止的方法一共3種

  • ①分配給線程的函數return,該線程會退出

  • ②線程調用了pthread_exit,該線程就會退出

  • ③其他線程(一般是主線程)調用pthread_cancel取消線程



線程分離

主線程也可以不等待新線程,自己干自己的事
但是線程并不提供非阻塞等待

而是通過修改新線程的被等待狀態,來做到

線程有兩種被等待的狀態

  • joinable:線程需要被join等待和回收(新線程默認是joined狀態

  • detach:線程分離(這種狀態的線程執行完了就直接退出,即使主線程調用pthread_join專門去等待分離狀態的線程,也會因為檢測到它是分離狀態,主線程直接返回,不會阻塞

此時要注意一點:
如果線程a和主線程分離了,如果線程a還在運行,主線程就退出了
這個時候可能:[不同的線程庫實現不一樣]

  • ①因為主線程退出,進程就直接也退出了
  • ②主線程退出,但是進程沒退出

注意:
多執行流時,盡可能保證主執行流最后退出=



線程庫的理解

線程id

我們使用的pthread庫里面的接口的時候,使用的事線程id來操縱線程

但是線程id并不是Linux內核中的LWP,而是線程庫pthread自己維護的

線程id的本質是地址,是線程庫維護的這個線程對應的結構體(tcb)變量的起始地址

創建線程的時候,不僅Linux內核中會創建一個LWP描述線程的內核級屬性,線程庫pthread中也會創建一個TCB結構體變量來維護線程的用戶級屬性
即線程庫中,會對線程進行先描述,再組織

為什么?

  • ①LWP是描述輕量級進程的,但是用戶使用的是線程,所以用戶需要的是線程的屬性,而不是輕量級進程的屬性
    LWP并不能非常好地描述用戶所需的線程的屬性(比如:LWP中沒有維護這個線程的棧大小,而線程庫TCB中維護了)

  • ②為了解藕
    因為用戶使用的是線程庫,線程庫創建出來的線程是用戶級線程
    用戶級線程不宜和內核級線程共用結構體和數據結構,這樣耦合度太高,而且還要使用系統調用陷入內核


線程庫哪里來的空間對線程先描述再組織?
線程庫維護進程的線程使用的空間是進程自己申請的物理內存(即使用進程的共享區內存來存儲

因為這樣描述線程屬性的結構體變量才有虛擬地址,執行流執行線程的庫函數的時候,才能找到并訪問到對應的數據

所以就可以做到:
不同的進程,使用同一個線程庫,但線程庫中維護的線程是不一樣的
但是線程庫的代碼區的代碼是一樣的



線程TCB的存放和內容

TCB的存儲

線程庫中TCB的存儲是在共享區中開辟一塊內存,把所有TCB以及對應的連續存儲在一起的

在這里插入圖片描述

TCB中的內容

  • ①對應的輕量級進程的LWP
  • ②對應進程的pid
  • ③void*result:分配給自己這個線程的函數的返回值
  • ④用戶分配給自己這個線程的入口函數的地址,以及它對應的參數
  • ⑤自己這個線程對應的棧的起始虛擬地址,以及棧的大小
  • ⑥線程對應的線程局部存儲的起始地址,及其大小
  • ⑦標記線程是否分離的bool類型的變量


線程的棧

線程的棧是獨立的,分兩種

  • ①進程地址空間中所謂的棧區,其實是專門給主線程用的棧區,大小是不固定的,可以擴容(當然也受到mm_struct的區域劃分限制

  • ②新線程的棧區是在創建新線程的同時,使用mmap在共享區開辟的一塊的大小固定(一般默認是8MB,如果用滿了8MB還用就會棧溢出)的內存

所以才說線程的棧是獨立的



線程局部存儲

一個全局變量b本來是被所有線程共享的,所有線程訪問這個的全局變量b時,訪問的虛擬地址是同一個

如果定義時,給全局變量b前面加一個__thread那么這個全局變量b就不是被所有線程共享的了,不同線程訪問這個變量b時,訪問的虛擬地址不同

這是怎么做到的?
如果一個變量a定義時加了__thread,編譯器編譯的時候,如果創建了新線程,就會在這個線程的線程局部存儲中開辟空間存儲一份這個變量a
以后這個線程訪問這個變量a的時候,就只訪問自己線程局部存儲中的變量a

注意:
__thread只能修飾內置類型的變量

線程局部存儲的作用:

  • ①不同線程對應一個獨立的錯誤碼,比如C標準庫提供的errno

  • ②緩存線程屬性等訪問頻繁的數據,提高訪問速度

比如:
可以加__thread定義一個全局的線程id,在對應線程里面初始化之后
這樣以后使用線程id,就不需要在調用pthread_self,直接用它,不同的線程看到的也是自己的id

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84412.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84412.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84412.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 任務調度策略

🌟 概述 Linux 內核以線程(任務)為單位進行調度,支持 SCHED_FIFO 和 SCHED_RR(實時調度)以及 SCHED_OTHER(基于 CFS,非實時調度)。 🔍 調度策略 1. SCHED_…

芯片金屬層M1、M2區別

在芯片設計中,M1(第一層金屬)和 M2(第二層金屬)是常見的金屬層,它們在用途、布線方向、設計規則和應用場景等方面存在一些主要區別。以下是詳細對比: 1. 用途 M1(第一層金屬&#x…

Linux離線環境下安裝Lean 4開發環境的完整指南

文章目錄 一、準備工作1. 在線環境下載必要文件2. 傳輸文件至離線環境 二、安裝elan工具鏈管理器1. 解壓并安裝elan2. 配置環境變量3. 驗證elan安裝 三、安裝Lean 4二進制包1. 解壓Lean 4二進制文件2. 注冊工具鏈到elan 四、安裝VS Code Lean 4插件1. 使用VS Code界面安裝插件 …

ffmpeg windows 32位編譯

ffmpeg windows 32位編譯 編譯后程序下載 編譯方式 自動編譯工具套件 – https://github.com/m-ab-s/media-autobuild_suite github克隆完成后,雙擊bat文件打開編譯窗口,注意git檢出的目錄需要簡短,最好選一個盤的根目錄。 選擇編譯版本…

P1216 [IOI 1994] 數字三角形 Number Triangles

題目描述 觀察下面的數字金字塔。 寫一個程序來查找從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。每一步可以走到左下方的點也可以到達右下方的點。 在上面的樣例中,從 7 → 3 → 8 → 7 → 5 7 \to 3 \to 8 \to 7 \to 5 7→3→8→7→5 的…

(二)原型模式

原型的功能是將一個已經存在的對象作為源目標,其余對象都是通過這個源目標創建。發揮復制的作用就是原型模式的核心思想。 一、源型模式的定義 原型模式是指第二次創建對象可以通過復制已經存在的原型對象來實現,忽略對象創建過程中的其它細節。 ?? 核心特點: 避免重復初…

Css實現懸浮對角線邊框動效

動畫效果展示 鼠標懸停時,一個帶有圓角的水綠色邊框會從右上和左下兩個方向快速展開,隨后顏色緩慢填充;移出鼠標時顏色先褪去,邊框再快速收縮消失,形成具有節奏感的呼吸式動畫。 📜 動畫原理說明 一、核…

技術創新究竟包含什么?

技術創新指的是引入新技術或改進現有技術,以創造新穎且更優的產品、服務或流程的過程。它涉及應用科學和技術知識開發創新解決方案,以創造價值、提高效率、推動增長,并滿足用戶和客戶不斷變化的需求。 技術創新可以有多種形式,例…

ArcGIS+AI:涵蓋AI大模型應用、ArcGIS功能詳解、Prompt技巧、AI助力的數據處理、空間分析、遙感分析、二次開發及綜合應用等

🌐 GIS憑借其強大的空間數據處理能力、先進的空間分析工具、靈活的地圖制作與可視化功能,以及廣泛的擴展性和定制性,已成為地理信息科學的核心工具。它在城市規劃、環境科學、交通管理等多個學科領域發揮著至關重要的作用。與此同時&#xff…

數據淘金時代:公開爬取如何避開法律雷區?

首席數據官高鵬律師團隊編著 一、“數字淘金熱”里的暗礁:那些被爬垮的平臺和賠哭的公司 前陣子某電商平臺的“商品比價爬蟲”上了熱搜,技術小哥本想靠抓競品數據優化定價,結果收到法院傳票——對方服務器被爬癱瘓,索賠300萬。這…

在ARM 架構的 Mac 上 更新Navicat到17后連接Oracle時報錯:未加載 Oracle 庫。

一:問題 使用的M1芯片的Mac,將Navicat更新到了17版本后,原本正常的Oracle數據庫無法連接,報錯:未加載 Oracle 庫。而sqlserver庫可以正常連接 二:解決方法 打開聚焦搜索——〉打開訪達——〉在應用程序中…

Springboot仿抖音app開發之用短視頻務模塊后端復盤及相關業務知識總結

Springboot仿抖音app開發之用戶業務模塊后端復盤及相關業務知識總結 BO類和VO類的區別 BO (Business Object) - 業務對象 定義: 業務對象是包含業務邏輯的領域模型用途: 主要用于封裝業務邏輯相關的數據,在業務層(Service層)之間傳遞特點: 與業務處理密切相關通常…

SQL-事務(2025.6.6-2025.6.7學習篇)

1、簡介 事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要么同時成功,要么同時失敗。 默認MySQL的事務是自動提交的,也就是說&#xff0…

《Ansys SIPI仿真技術筆記》 E-desk IBIS模型導入

技術筆記日期:20250611 00 背景和疑問 當在Circuit中準備載入IBIS時,工作界面會彈出如下界面: 那么具體Pin Import和Buffer Import有和區別? 何時該按哪個導入呢? 01 思考和記錄 1. Buffer Import VS Pin Import…

uniapp的請求封裝,如何避免重復提交請求

1、如何封裝uniapp,并且如何使用uniapp的封裝查看👉uniapp請求封裝_uni-app-x 請求封裝-CSDN博客??????? 2、聲明一個請求記錄的緩存,代碼如下 // 存儲請求記錄 let requestRecords {}; // 重復請求攔截時間(毫秒&#x…

【云原生】阿里云SLS日志自定義字段標簽實現日志告警

把業務日志接入到阿里云SLS日志服務后,我們想自定義字段做為標簽,在做日志告警的時候,可以做為查詢結果使用 自定義標簽 樣例: 一個典型的java log初始化日志格式 [ywgy-app-service:10.10.6.100:30000] 2025-06-10 08:40:53.444 INFO 1[TID: N/A][uId:][sId:][tId:][po…

Linux下制作Nginx綠色免安裝包

linux下安裝nginx比較繁瑣,遇到內網部署環境更是麻煩。根據經驗將nginx打包一個綠色版進行使用。 大體思路,在一臺正常的機器上面制造好安裝包,然后上傳到內網服務器,解壓使用 安裝包制作 安裝依賴 yum install gcc-c pcre per…

腦機新手指南(七):OpenBCI_GUI:從環境搭建到數據可視化(上)

一、OpenBCI_GUI 項目概述 (一)項目背景與目標 OpenBCI 是一個開源的腦電信號采集硬件平臺,其配套的 OpenBCI_GUI 則是專為該硬件設計的圖形化界面工具。對于研究人員、開發者和學生而言,首次接觸 OpenBCI 設備時,往…

【Zephyr 系列 18】分布式傳感網絡系統設計:從 BLE Mesh 到邊緣網關的數據閉環

??關鍵詞:Zephyr、BLE Mesh、邊緣網關、分布式網絡、狀態同步、組播、數據聚合、遠程控制 ??適合人群:希望實現 BLE Mesh 與網關聯合控制、多設備組網協作、數據閉環采集的開發者 ??預計字數:5500+ 字 ?? 背景與系統目標 在工業、農業、倉儲等場景中,我們常見以下…

【區塊鏈基礎】區塊鏈的 Fork(分叉)深度解析:原理、類型、歷史案例及共識機制的影響

區塊鏈的 Fork(分叉)全面解析:原理、類型、歷史案例及共識機制的影響 在區塊鏈技術的發展過程中,Fork(分叉)現象是不可避免且極具影響力的一個環節。理解區塊鏈分叉的形成原因、具體表現以及共識機制對分叉的作用,對于深入把握區塊鏈技術架構及其治理機制至關重要。 本…