中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

【Linux】--程序地址空間-創(chuàng)新互聯(lián)

目錄

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),云夢企業(yè)網(wǎng)站建設(shè),云夢品牌網(wǎng)站建設(shè),網(wǎng)站定制,云夢網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,云夢網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

程序地址空間

進程地址空間 - 虛擬地址空間

概念引入(淺)

初步理解結(jié)構(gòu)

深入理解虛擬地址

為什么要有地址空間?

程序地址空間的角度理解掛起


程序地址空間

C/C++在Linux下的程序地址空間分布:

  • 棧向低地址增長,堆向高地址增長(堆、棧相對而生)
  • 正文代碼區(qū)包括其中的字符常量區(qū),只能讀不能寫
#include#includeint un_g_val;
int g_val = 10;

int main(int argc, char* argv[], char* env[])
{
    printf("代碼區(qū):%p\n", main);      //代碼區(qū)

    char* p = "hello world";         //字面常量
    printf("字面常量:%p\n", p);

    printf("已初始化全局數(shù)據(jù)區(qū):%p\n", &g_val);    //已初始化全局數(shù)據(jù)區(qū)

    static int num = 10;
    printf("static修飾的局部變量:%p\n", &num);    //static
    printf("未初始化全局數(shù)據(jù)區(qū):%p\n", &un_g_val); //未初始化全局數(shù)據(jù)區(qū)
    
    char* p1 = (char*)malloc(4);
    char* p2 = (char*)malloc(4);
    char* p3 = (char*)malloc(4);
    
    printf("堆1:%p\n", p1);         //堆
    printf("堆2:%p\n", p2);         //堆
    printf("堆3:%p\n", p3);         //堆
    printf("棧1:%p\n", &p1);        //棧
    printf("棧2:%p\n", &p2);        //棧
    printf("棧3:%p\n", &p3);        //棧

    for(size_t i = 0; i< argc; ++i)
    {
        printf("argv[%d]:%p\n", i, argv[i]);
    }
    for(size_t i = 0; env[i]; ++i)
    {
        printf("env[%d]:%p\n", i, env[i]);
    }
    return 0;
}

在我們看來,父子進程是代碼共享的,所以&g_val地址相同是可以理解的,父進程具有獨立性,所以子進程的g_val改變父進程的g_val不變是可以理解點,但是結(jié)合起來看,具有相同地址的變量卻是不同值,就很奇怪。

? 其實,這里地址并不是物理上的地址,而是:虛擬地址(線性地址)。操作系統(tǒng)上的地址與編程語言上的地址是不一樣的,不是一個理解。幾乎所有有?“地址” 的概念的語言,其所謂的地址一定不是物理地址,而是虛擬地址。在操作系統(tǒng)上,接觸不到物理地址,都是虛擬地址,這是操作系統(tǒng)自我的一種保護,防止空間被隨意的更改。

虛擬地址:計算機通過軟硬結(jié)合的方案,創(chuàng)造出的地址空間的概念。

進程地址空間 - 虛擬地址空間 概念引入(淺)

初步理解進程地址空間是虛擬地址空間的意義。(計算機的演變)

最初,其實并沒有虛擬地址空間的概念,是CPU直接對物理地址空間(內(nèi)存)操作。

由于物理地址空間就是自由的空間,并未對讀寫設(shè)置權(quán)限,也沒有違規(guī)操作的處理:

  • 物理地址空間沒有隔離,每一個進程都可以修改其他進程的數(shù)據(jù),修改內(nèi)核空間中的數(shù)據(jù)。
  • 由于是直接存儲于物理空間內(nèi),所以進程數(shù)據(jù)必須統(tǒng)一規(guī)范性放置,會出現(xiàn)碎片化內(nèi)存浪費。
  • 內(nèi)存地址隨機分配,程序運行的地址不確定,CPU需要查詢消耗。

初步總結(jié):我們需要一個處理方式,使得CPU運行進程的操作是規(guī)范的,安全的;對于物理地址空間中的進程管理是合理的。


這樣就有了虛擬地址空間的概念。虛擬地址空間的存在就如同一幅圖,一把尺。

一幅圖:

? 直接給進程一個?0x0000……0000 到 0xffff……ffff 的空間,并把每個區(qū)域進行劃分,將代碼與數(shù)據(jù) “畫” 在圖(虛擬地址空間)中。CPU也無需關(guān)注物理內(nèi)存的存在,只需要根據(jù) “圖” 中的位置進行訪問即可,剩下的轉(zhuǎn)換交給操作系統(tǒng),操作系統(tǒng)轉(zhuǎn)換 “圖” 中的虛擬地址變?yōu)槲锢淼刂?,然后將?shù)據(jù)輸出給CPU。也就是說:每一個進程都有一幅針對它的 “圖”,這副 “圖” 是每個進程私有的,而在轉(zhuǎn)換的過程中就是檢測CPU操作是否規(guī)范的關(guān)鍵所在。

? CPU根據(jù)虛擬地址空間的位置向操作系統(tǒng)索要數(shù)據(jù)。

一把尺:

? 對于虛擬的?0x0000……0000 到 0xffff……ffff 區(qū)域的劃分,區(qū)域的劃分就是begin與end:

初步理解結(jié)構(gòu)

操作系統(tǒng)將虛擬地址空間中的地址轉(zhuǎn)換為物理地址是通過所謂的頁表。

? CUP通過運行進程,以進程的task_struct結(jié)構(gòu)題提取到虛擬地址空間中所儲存的虛擬地址,該虛擬地址再以頁表的映射關(guān)系找到物理地址,再以此到物理空間中讀取數(shù)據(jù)??梢哉f整個過程CPU都是不知道物理內(nèi)存的存在的,而一直認為虛擬地址空間就是數(shù)據(jù)真正處于的位置。

地址空間和頁表是每一個進程都私有的一份,以每個進程的頁表的映射關(guān)系就能做到:

  • 通過映射,虛擬地址與物理地址對應(yīng),就能做到,進程之間不會互相干擾,保證進程的獨立性。
  • 只有頁表中的虛擬地址,或者虛擬地址相對應(yīng)的物理空間才能訪問。就能提高安全性,防止出現(xiàn)野指針越界訪問其他進程的問題。

解決前面的父進程與子進程具有相同的地址,卻g_val值不同的問題:?

fork之后,代碼是父子共享的,所以子進程的地址空間與頁表絕大多數(shù)數(shù)據(jù)都是復(fù)制的父進程的地址空間與頁表數(shù)據(jù),二者是一樣的,前提是并未在子或父進程中更改數(shù)據(jù)。

? 當(dāng)我們更改子進程的g_val的數(shù)據(jù)時:

? 操作系統(tǒng),會以實時拷貝,開辟一個空間將g_val復(fù)制拷貝,改變子進程頁表的映射關(guān)系改變成新開辟的空間,然后進行子進程的g_val的數(shù)據(jù)更改。我們表面上所看的地址只是虛擬地址,其實在物理內(nèi)存中,有屬于自己的變量空間,只不過在用戶層使用同一個變量(虛擬地址)來標(biāo)識。

深入理解虛擬地址

? 當(dāng)我們的程序在編譯的時候(形成可執(zhí)行程序的時候),或者說沒被加載到內(nèi)存當(dāng)中的時候,程序內(nèi)部其實就已經(jīng)有地址了。

?地址空間不僅僅是操作系統(tǒng)需要遵守的,其實編譯器也要遵守。即編譯器編譯代碼的時候,就已經(jīng)形成了各個區(qū)域、代碼區(qū)、數(shù)據(jù)區(qū)……,并且采用個Linux內(nèi)核中的一樣的編址方式,給每一個變量,每一行代碼都進行了編址。

? 所以:程序在編譯的時候,每一個字段其實早就已經(jīng)具有了一個虛擬地址。

? 其實這正是地址空間與頁表,最開始的時候的數(shù)據(jù)來源。

為什么要有地址空間?

1、凡是非凡的訪問或者是映射,操作系統(tǒng)都會識別到,并終止此進程。

? 因為地址空間和頁表是操作系統(tǒng)創(chuàng)建并維護的。這也就意味著凡是想用地址空間和頁表進行映射,就一定要在操作系統(tǒng)的監(jiān)管之下來進行訪問。也便保護了物理內(nèi)存中所有的合法數(shù)據(jù),包括各個進程以及內(nèi)核的相關(guān)有效數(shù)據(jù)。

更直接的說就是:有效的保護了物理地址。

  • 所訪問的虛擬地址是頁表未有的,即訪問不合法。
  • 虛擬地址所訪問的物理地址是頁表未映射的,即訪問不合法。
  • 頁表中不僅有映射關(guān)系,更有讀寫權(quán)限。此也是自由的物理內(nèi)存,卻有只能讀的代碼區(qū)的關(guān)鍵。

2、因為有地址空間和頁表的存在,所以在物理內(nèi)存中,可以對未來的數(shù)據(jù)進行任意的位置加載。

? 由于進程與內(nèi)存的聯(lián)系以頁表分隔。對于虛擬地址在內(nèi)存中的物理地址存儲,是由頁表的映射而聯(lián)系的,所以內(nèi)存管理模塊與進程管理模塊就完成了解耦合。

? 所以如C/C++語言上的new、malloc申請空間的時候,本質(zhì)就是在虛擬空間申請。因為對于物理空間申請了,但是無法立馬使用,就會造成空間的浪費,而由于兩個模塊的解耦合,那么兩個模塊的聯(lián)系也就是一個頁表,對于物理空間并沒有立馬給與的必要。只需延遲分配的策略,就可以提高整機的效率。

? 之所以可以延遲分配,本質(zhì)上:因為有地址空間的存在。所以地址 “許諾” 給進程就可以了,上層申請空間就是在地址空間上申請,物理內(nèi)存可以一個bit為都不給。進程既不是立馬運行,那就延遲實現(xiàn)?“許諾” ,提高內(nèi)存的使用。而當(dāng)你真正的對物理地址空間訪問的時候,才執(zhí)行內(nèi)存的相關(guān)管理算法,申請空間,構(gòu)建頁表映射關(guān)系)

?內(nèi)存管理操作系統(tǒng)自動完成。用戶、CPU、進程完全0感知。

3、根據(jù)2,因為在物理內(nèi)存中理論可以任意位置加載,那么物理內(nèi)存中的幾乎所有數(shù)據(jù)和代碼在內(nèi)存中都是亂序的。

? 因為頁表的存在,它可以將地址空間上的虛擬地址與物理地址進行映射,所以可以做到在進程的視角中所有的內(nèi)存分布,是有序的。

?重點:地址空間+頁表 = 內(nèi)存亂序分布變的有序化。

? 不同進程的需要訪問的物理內(nèi)存中的代碼和數(shù)據(jù),是由頁表規(guī)范化,映射到不同的物理內(nèi)存中,進而可以做到進程的獨立性。

?重點:地址空間+頁表 =?內(nèi)存亂序分布變的獨立化。

實現(xiàn)的有序化、獨立化,更是由于地址空間的存在。因為每一個進程都認為自己有一個4GB空間(32位),進而有了虛擬地址分布的地址空間,并通過頁表映射到不同的區(qū)域,實現(xiàn)有序化、獨立化。

程序地址空間的角度理解掛起

? 加載的本質(zhì)就是創(chuàng)建進程,按照前面第3點,并不是必須把所有程序的代碼和數(shù)據(jù)加載到內(nèi)存中,并創(chuàng)建內(nèi)核數(shù)據(jù)結(jié)構(gòu)建立映射關(guān)系。在極端的情況下,甚至可能只有內(nèi)核結(jié)構(gòu)被創(chuàng)建出來,并未分配物理空間,這就是未了提高內(nèi)存利用率進行的分批加載,同樣的也有分批換出。

? 當(dāng)已被執(zhí)行完的代碼與數(shù)據(jù),或者由于處于對于某種資源的等待導(dǎo)致的阻塞,也就是此進程短時間不會再執(zhí)行了。進程的數(shù)據(jù)和代碼就換出,也就叫做掛起。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

本文名稱:【Linux】--程序地址空間-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://m.rwnh.cn/article0/cejsoo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站服務(wù)器托管、搜索引擎優(yōu)化品牌網(wǎng)站建設(shè)、全網(wǎng)營銷推廣、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
洞口县| 周口市| 临武县| 永寿县| 都安| 梓潼县| 怀集县| 双峰县| 那曲县| 鄢陵县| 会泽县| 长兴县| 密山市| 祁门县| 宁津县| 禄丰县| 泰和县| 长丰县| 高青县| 墨江| 柳林县| 乐亭县| 龙州县| 阜城县| 卢龙县| 广灵县| 长垣县| 呼和浩特市| 河池市| 潍坊市| 句容市| 太仆寺旗| 体育| 阳谷县| 南城县| 长丰县| 象山县| 盐亭县| 南京市| 康定县| 固阳县|