欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux地址空間的轉(zhuǎn)換以及線程的理解和使用過程

 更新時間:2025年07月11日 10:16:28   作者:海綿寶寶de派小星  
文章解析了線程與進程的關(guān)系,指出線程是進程內(nèi)的執(zhí)行分支,Linux通過復(fù)用PCB實現(xiàn)輕量化管理,并詳細說明了頁表分級機制(如兩級頁表)與4KB頁框的內(nèi)存映射原理,同時對比線程的優(yōu)缺點,強調(diào)其資源高效性與共享風(fēng)險

本篇主要進行對于進程和線程的理解,以及對于線程的一部分使用方法和使用的原理

線程的理解

首先回顧前面一篇的內(nèi)容中,對于進程的基本認(rèn)識:

什么是線程,如何理解線程?

線程是進程內(nèi)部的一個執(zhí)行分支,那么也就意味著肯定是先有進程,再有線程,這也是最基本的一個邏輯,那么在Linux系統(tǒng)中也確實是這樣,當(dāng)一個代碼被編譯完成之后,如果想要執(zhí)行這個進程,那么在進行啟動這個進程的時候,就會對這個進程建立起對應(yīng)的地址,空間,頁表,代碼數(shù)據(jù),內(nèi)存區(qū)域的映射關(guān)系等等,這些就都是對于進程在創(chuàng)建之初就應(yīng)該要儲備好的部分,后續(xù)在用特定的方案創(chuàng)建一個PCB的時候,其實只需要讓多個PCB去指向同樣的一部分內(nèi)容,就可以實現(xiàn)在共享地址空間中做到讓多個不同的執(zhí)行流去訪問同一塊進程內(nèi)的代碼和數(shù)據(jù),那么對于進程的代碼和數(shù)據(jù)資源進程合理的劃分,就能實現(xiàn)讓這些代碼之間的串行變成并發(fā)執(zhí)行,那么這一個一個的分支就叫做線程,因此基于上述的這兩個點,可以得出下面的結(jié)論

  1. 線程在創(chuàng)建和釋放的時候可以比進程更加輕量化,只需要對于各種各樣的PCB進行管理即可
  2. 線程是進程內(nèi)部的執(zhí)行流,本質(zhì)上線程是在進程的地址空間中進行運行的
  3. 對于進程的理解應(yīng)該更加深一點:在之前的理解中,進程就是代碼和數(shù)據(jù)以及內(nèi)核的數(shù)據(jù)結(jié)構(gòu),這個結(jié)論是沒有任何問題的,但是放在現(xiàn)在要多一個新的理解,進程是承擔(dān)分配系統(tǒng)資源的基本實體,具體是如何進行承擔(dān)的,簡單來說就是從各種的內(nèi)核數(shù)據(jù)結(jié)構(gòu)和表現(xiàn)上來體現(xiàn)的,就是要花內(nèi)存占用對應(yīng)的CPU資源,這樣就是體現(xiàn)出分配系統(tǒng)資源的基本實體
  4. 有了對于線程的理解,那么在之前對于進程的理解就應(yīng)該更加廣泛一些,之前對于進程的理解是體現(xiàn)在了內(nèi)部只有一個PCB結(jié)構(gòu),這樣的進程在現(xiàn)在看來是可以叫做是一個執(zhí)行流的進程,現(xiàn)在對于進程就轉(zhuǎn)換成了一個進程內(nèi)會包含有一大堆的申請的資源,并且還會有至少一個的PCB結(jié)構(gòu),而多線程其實就是內(nèi)部有多個這樣的PCB結(jié)構(gòu),這就實現(xiàn)了一個單進程中有多線程
  5. Linux當(dāng)中線程和進程都會被 操作系統(tǒng)調(diào)度,那么現(xiàn)在的問題是,是否需要重新設(shè)計一個線程的結(jié)構(gòu)呢?事實上從Linux的操作系統(tǒng)設(shè)計模式中可以看出并沒有這樣做,而是把之前對于進程的相關(guān)字段都重新復(fù)用了起來,也就是說Linux中的線程設(shè)計是完全用進程來進行模擬的,站在CPU的角度來說,當(dāng)它拿到一個具體的PCB結(jié)構(gòu)執(zhí)行流的時候,它認(rèn)為自己將來在CPU上跑的時候的執(zhí)行的那個PCB,是要比傳統(tǒng)意義上理解的那個單個進程PCB是不一樣的,最起碼是小于等于單PCB的進程,所以自此之后,可以換一個角度去看Linux中的進程,可以把進程線程都看做事一個輕量級的進程,這個輕量級的進程指的就是單純這個PCB,而對應(yīng)的整個地址,比如有地址空間頁表等等信息,這些全部加起來就叫做是真正意義上的進程,而并非是輕量級進程

地址空間的轉(zhuǎn)換問題

下面要談的一個問題是虛擬到物理地址轉(zhuǎn)換的問題,這個問題其實已經(jīng)提過了,在最初對于進程的理解中就已經(jīng)有了一個初步的描述,在前面的對于地址空間的轉(zhuǎn)換問題的理解只是停留在于,從虛擬地址到物理地址是要進行頁表的映射 進行轉(zhuǎn)換,而這樣的理解其實并不是特別到位的,下面這個模塊將對于這個過程進行更加詳細的描述和理解

在之前對于文件系統(tǒng)的理解當(dāng)中,提及過這樣的一個觀點,文件系統(tǒng)最終會指導(dǎo)操作系統(tǒng)和磁盤的設(shè)備進行io交互的時候,是以4kb為一個單位進行數(shù)據(jù)交互的,那么這個4kb也被叫做是一個文件塊,換句話說,站在操作系統(tǒng)的角度來講,它并不關(guān)心這個數(shù)據(jù)是啥,到底是圖片還是視頻還是音頻,它關(guān)心的是讀取這個文件的內(nèi)容,要從外設(shè)搬到內(nèi)存中,是要以一個數(shù)據(jù)塊為一個單位進行搬運的,那在進程間通信的時候,也提及過對于共享內(nèi)存的創(chuàng)建大小,必須要以這個配置為單位

為了方便描述,畫出下面的最初步的示意圖

在上述的這個系統(tǒng)中,物理內(nèi)存和磁盤進行io交互的時候,在硬件的層面上,可以通過某種方式把數(shù)據(jù)從磁盤弄到內(nèi)存當(dāng)中,而從純硬件的角度來講,這個過程就是把數(shù)據(jù)從一個設(shè)備拷貝到另外一個設(shè)備上,但是現(xiàn)在的一個問題是,把數(shù)據(jù)加載到內(nèi)存的什么位置?加載多少?從哪里開始加載?這些問題都是需要解決的,甚至以至于還有比如說這個數(shù)據(jù)的訪問權(quán)限是多少,這個數(shù)據(jù)的屬性是什么,這些問題本質(zhì)上來說就已經(jīng)不屬于是硬件的范疇了,那這個問題的解決措施是由操作系統(tǒng)中的文件系統(tǒng)來解決的,文件系統(tǒng)把磁盤整體進行一個管理,那么此時文件系統(tǒng)就可以通過文件路徑來把對應(yīng)的文件打開,再把對應(yīng)的數(shù)據(jù)塊中的信息加載到物理內(nèi)存中,從而實現(xiàn)了一個文件的加載和讀取的過程,而這個過程其實也是在之前的理解范圍之內(nèi)的

這里要引出的一個結(jié)論就是,不管是什么數(shù)據(jù),可能是這個文件的內(nèi)容,也可能是這個文件的屬性,但只要是屬于這個文件的數(shù)據(jù)范圍內(nèi),它在進行加載的時候的基本單位就是4kb,這是由文件系統(tǒng)來進行設(shè)置的,也就是說在文件系統(tǒng)的層面上看這個新建的hello.exe這個可執(zhí)行程序,本質(zhì)上可以看成是由若干個小的4kb這樣的文件塊組成的,一般給這樣的數(shù)據(jù)段叫做是ELF數(shù)據(jù)段,那么最終的結(jié)論是,這里的每一個數(shù)據(jù)塊都是4kb為單位的,那么在最終的操作系統(tǒng)中,本質(zhì)上也會這樣進行劃分,而這樣的每一個這樣的4kb大小的數(shù)據(jù)塊,在磁盤的角度看來就叫做是頁幀,而在物理空間中的這個4kb的一塊一塊的空間就被叫做是頁框,所以上面的圖可以修改為下面的模樣:

那么這樣就能得出一個樸素的結(jié)論是,未來這個文件當(dāng)中哪怕只是需要修改一個比特位,也必須要把這個數(shù)據(jù)所在的這個4kb的數(shù)據(jù)塊全部弄出來加載到內(nèi)存中,在內(nèi)存中進行修改后,再刷新到磁盤上,這個就是基本單位的含義

下面的一個問題是,既然物理空間被劃分成了這樣,那么實際上計算一下:

在地址空間中按4kb的劃分,是需要有100多萬個頁框的,這是一個相當(dāng)龐大的數(shù)據(jù),那么下一個問題是,對于這個頁框的管理該如何進行管理呢?所以操作系統(tǒng)的內(nèi)部會維護一個結(jié)構(gòu)體對象,用來描述這個頁框的屬性,而在操作系統(tǒng)中就存在這樣一個數(shù)組,用來描述這個結(jié)構(gòu)體,可以近似的理解為是struct page pages[1048576],而在這個結(jié)構(gòu)體page中,里面存在了很多的字段,這些字段可能是意味著有物理內(nèi)存是否被鎖定,也有這段內(nèi)存是否被使用,當(dāng)前內(nèi)存是否準(zhǔn)備釋放,每一種情況都用一個比特位來表示,所以在內(nèi)存中對于物理內(nèi)存的管理,就可以轉(zhuǎn)換成對于這個標(biāo)記位的每一個比特位的管理

下一個問題是,頁表的大小問題,在虛擬地址中有2^32個地址,這些地址都要被頁表進行映射嗎?經(jīng)過簡單的計算就可以很容易知道,這是不可能的,如果每一個地址都進行映射,那么頁表所占據(jù)的空間可能就已經(jīng)是一個很大的概念了,所以得出的一個結(jié)論是,上面圖中的這個頁表其實是不完全準(zhǔn)確的,真正的頁表結(jié)構(gòu)還有其他的結(jié)構(gòu)組成

虛擬到物理地址到底是如何進行轉(zhuǎn)換的呢?在CPU中有很多的寄存器,其中一個寄存器叫做eip,那這個寄存器主要是存儲的是虛擬地址,而在CPU上還會有一個小組件叫做MMU,那這個組件其實就可以理解為可以完成從虛擬到物理地址的轉(zhuǎn)換工作,那這個轉(zhuǎn)換是如何進行轉(zhuǎn)換的?

以32位的機器為例,現(xiàn)在有一個地址,假設(shè)它是1111 1111 1001 0001 0000 0000 0010 1000,那么在實際的內(nèi)存中其實并不會把這32個數(shù)字看成一個整體,而是會把前10個數(shù)字看出一個整體,中間10個數(shù)字看成一個整體,后面的12個數(shù)字看成一個整體,而實際上頁表也并非是一個大的頁表,而是會存在分級的情況,按32位的機器來看,會分成兩級,第一級叫做是頁目錄,頁目錄整體上來說是被用作查找的,但是頁目錄的查找只會使用前10個比特位,那頁目錄總共會有多少個呢?經(jīng)過計算總共會有1024個組合方式,那么在之后進行查詢頁表的時候,就會先找到前10位對應(yīng)的內(nèi)容,再用中間的十位進行查找,那中間的這10位就被叫做是頁表項,也叫做是二級頁表,在實際進行查找的時候,可以把前10個轉(zhuǎn)換成一個二進制的數(shù)字,而這個數(shù)字就對應(yīng)了這個數(shù)組的下標(biāo),而這個數(shù)組里面的內(nèi)容指向的是下一級的頁表,從這個開始的地方就能搜索到下一級的頁表是誰,那么實際上,在這個一級頁表中其實存儲了的是一個映射關(guān)系,而這個第一部分的內(nèi)容是不需要被存儲起來的,直接把前10個比特位當(dāng)成是一個數(shù)組的下標(biāo)用就可以了,實現(xiàn)了一個二進制的拆分機制

那為什么要這樣做,這樣做的好處在哪里?實際上頁表的存儲是物理內(nèi)存的哪個位置,本身我們也不清楚,所以當(dāng)前在進行頁表的構(gòu)建的時候,從虛擬地址映射的這個過程中,如果沒有對應(yīng)的這級頁表,在進行重新申請的時候就填到這個里面,最終凡是從這個地址開始的都會通過這個頁表來查,而這個頁表也可以當(dāng)成是一個數(shù)組,而這個數(shù)組其中也有10個比特位,也就是1024,那么這個數(shù)字實際上也可以看出是一個數(shù)組的下標(biāo),里面存放的內(nèi)容就是實際這個地址最終映射到所要申請的頁框的起始地址,因為物理內(nèi)存的角度來講這個頁框的大小是以4kb進行io的,所以在實際進行尋找這個具體內(nèi)容的時候,就要通過先找到這個內(nèi)容屬于哪個頁框,再通過這個頁框找到內(nèi)部的這個內(nèi)容,那要找某一個數(shù)據(jù)或者是代碼,前提就是要找到虛擬地址所在的頁框,所以在這個頁表中存儲的就是物理內(nèi)存的頁框,因此,本質(zhì)上來說,對于頁表這個結(jié)構(gòu)來說,整個頁目錄和頁表項當(dāng)中真正有用的部分是幫助操作系統(tǒng)找到頁框,隨后再找到具體的對應(yīng)的內(nèi)容,而找到頁框之后,就可以根據(jù)最后的那12個比特位當(dāng)成是一個偏移量,來找到與之對應(yīng)的內(nèi)容數(shù)據(jù)了,來用下面的這個圖描述一下更為清楚:

借助這樣的結(jié)構(gòu),就可以使得整個頁表的體積大大減小,但是更為重要的是,此時找到的就是物理內(nèi)存中的頁框了,但是在平時進行訪問的時候其實并不關(guān)心頁框,關(guān)心的是頁框中的某一個數(shù)據(jù),但是只需要借助最后的偏移量就可以找到了,只需要由前10個比特位找到頁目錄,然后再通過下標(biāo)找到對應(yīng)的頁表,再通過中間的10個比特位找到對應(yīng)的頁表項,再通過頁表項的內(nèi)容找到頁框,再通過最后的這個偏移量來找到所需要的數(shù)據(jù)內(nèi)容

所以說,頁表中不存物理地址,但是會有頁框的物理地址,嚴(yán)格意義來說,它當(dāng)中只有頁框的物理地址,通過第二級索引就能找到物理內(nèi)存中頁框的物理地址,再根據(jù)偏移量就能直接定位到具體的地址了

完善一下剛才的圖:

總結(jié):

劃分頁表到底是什么呢?

劃分頁表的本質(zhì)是什么呢?本質(zhì)上來說,就是在劃分地址空間,站在進程的角度來講,地址空間本身就是資源,所以劃分頁表就是在劃分資源

線程的優(yōu)點

  1. 創(chuàng)建一個新線程的代價要比創(chuàng)建一個新進程小得多
  2. 與進程之間的切換相比,線程之間的切換需要操作系統(tǒng)做的工作要少很多
  3. 線程占用的資源要比進程少很多
  4. 能充分利用多處理器的可并行數(shù)量
  5. 在等待慢速I/O操作結(jié)束的同時,程序可執(zhí)行其他的計算任務(wù)
  6. 計算密集型應(yīng)用,為了能在多處理器系統(tǒng)上運行,將計算分解到多個線程中實現(xiàn)
  7. I/O密集型應(yīng)用,為了提高性能,將I/O操作重疊。線程可以同時等待不同的I/O操作

線程的缺點

性能損失:

  • 一個很少被外部事件阻塞的計算密集型線程往往無法與共它線程共享同一個處理器。
  • 如果計算密集型線程的數(shù)量比可用的處理器多,那么可能會有較大的性能損失,這里的性能損失指的是增加了額外的同步和調(diào)度開銷,而可用的資源不變

健壯性降低:

  • 編寫多線程需要更全面更深入的考慮,在一個多線程程序里,因時間分配上的細微偏差或者因共享了不該共享的變量而造成不良影響的可能性是很大的,換句話說線程之間是缺乏保護的

缺乏訪問控制:

  • 進程是訪問控制的基本粒度,在一個線程中調(diào)用某些OS函數(shù)會對整個進程造成影響

編程難度提高:

  • 編寫與調(diào)試一個多線程程序比單線程程序困難得多

線程的健壯性問題

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>

// 新線程
void *ThreadRoutine(void *arg)
{
    const char *threadname = (const char *)arg;
    while (true)
    {
        std::cout << "I am a new thread: " << threadname << ", pid: " << getpid() << std::endl;
        sleep(1);
    }
}

int main()
{
    // 已經(jīng)有進程了
    for (int i = 0; i < 5; i++)
    {
        char threadname[64];
        snprintf(threadname, sizeof(threadname), "%s-%d", "thread", i);
        pthread_t tid;
        pthread_create(&tid, nullptr, ThreadRoutine, (void *)threadname);
        sleep(1);
        if (i == 4)
            int a = 10 / 0;
    }
    return 0;
}

運行結(jié)果如下:

從中看出的一個問題是,當(dāng)出現(xiàn)除0錯誤的時候,所有的線程都被終止了,這是因為所有的線程都共享信號的處理方式,所以當(dāng)有一個線程收到信號后,其實所有的線程也就都被終止了

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • linux 定時休眠的實現(xiàn)思路

    linux 定時休眠的實現(xiàn)思路

    這篇文章主要介紹了linux 定時休眠的實現(xiàn)思路,休眠的類型有三種類型,文章對每種類型介紹的都很詳細,需要的朋友可以參考下
    2018-07-07
  • ROS控制Turtlebot3移動機器人的基礎(chǔ)教程

    ROS控制Turtlebot3移動機器人的基礎(chǔ)教程

    這篇文章主要給大家介紹了關(guān)于ROS控制Turtlebot3移動機器人的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 騰訊云ubuntu服務(wù)器tomcat訪問慢的原因分析及解決方法

    騰訊云ubuntu服務(wù)器tomcat訪問慢的原因分析及解決方法

    在騰訊云上配了個一元的學(xué)生云,開始一切正常,直到配置tomcat開始出現(xiàn)各種莫名其妙的問題。最終找到問題的原因。下面小編通過本教程給大家介紹下騰訊云ubuntu服務(wù)器tomcat訪問慢的原因分析及解決方法,一起看看吧
    2016-10-10
  • 解決虛擬機NAT模式無法上網(wǎng)問題

    解決虛擬機NAT模式無法上網(wǎng)問題

    文章主要介紹了確認(rèn)虛擬機網(wǎng)絡(luò)連接問題的兩個步驟:首先檢查虛擬機的IP地址是否與主機在同一網(wǎng)段,其次確保虛擬機相關(guān)服務(wù)已開啟
    2024-12-12
  • Ubuntu無法聯(lián)網(wǎng)的解決方法

    Ubuntu無法聯(lián)網(wǎng)的解決方法

    這篇文章主要為大家詳細介紹了Ubuntu無法聯(lián)網(wǎng)的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • Apache Hadoop版本詳解

    Apache Hadoop版本詳解

    本文總結(jié)了ApacheHadoop和Cloudera Hadoop的版本衍化過程,并給出了選擇Hadoop版本的一些建議。感興趣的朋友一起看看吧
    2017-09-09
  • Linux 安裝二進制MySQL 及 破解MySQL密碼的方法

    Linux 安裝二進制MySQL 及 破解MySQL密碼的方法

    這篇文章主要介紹了Linux 安裝二進制MySQL 及 破解MySQL密碼的方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • Linux中的LUN、磁盤、LVM和文件系統(tǒng)映射使用

    Linux中的LUN、磁盤、LVM和文件系統(tǒng)映射使用

    這篇文章主要介紹了Linux中的LUN、磁盤、LVM和文件系統(tǒng)映射使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • centos系統(tǒng)為php安裝memcached擴展步驟

    centos系統(tǒng)為php安裝memcached擴展步驟

    這篇文章主要介紹了centos系統(tǒng)為php安裝memcached擴展的步驟,大家參考使用吧
    2014-01-01
  • linux中ssh免密通信的實現(xiàn)

    linux中ssh免密通信的實現(xiàn)

    這篇文章主要介紹了linux中ssh免密通信的實現(xiàn),詳細的介紹了什么是ssh及其ssh免密通信,非常具有實用價值,需要的朋友可以參考下
    2018-11-11

最新評論