1. 一個(gè)爭(zhēng)議很大的問題(文末送書)

        共 4744字,需瀏覽 10分鐘

         ·

        2022-06-20 11:48

        粉絲福利:文末送書

        早上看到讀者在群里討論這些面試題:

        其中,第一個(gè)問題「在 4GB 物理內(nèi)存的機(jī)器上,申請(qǐng) 8G 內(nèi)存會(huì)怎么樣?」存在比較大的爭(zhēng)議,有人說會(huì)申請(qǐng)失敗,有的人說可以申請(qǐng)成功。

        這個(gè)問題在沒有前置條件下,就說出答案就是耍流氓。因?yàn)樵?32 位操作系統(tǒng)和 64 位操作系統(tǒng)場(chǎng)景下,答案是不同的。

        另外,我們還要看申請(qǐng)完 8G 內(nèi)存后會(huì)不會(huì)被使用,會(huì)被使用是一種情況,不會(huì)被使用又是另外一種情況了。

        所以,我們要分場(chǎng)景討論。

        正文

        應(yīng)用程序通過 malloc 函數(shù)申請(qǐng)內(nèi)存的時(shí)候,實(shí)際上申請(qǐng)的是虛擬內(nèi)存,此時(shí)并不會(huì)分配物理內(nèi)存。

        當(dāng)應(yīng)用程序讀寫了這塊虛擬內(nèi)存,CPU 就會(huì)去訪問這個(gè)虛擬內(nèi)存, 這時(shí)會(huì)發(fā)現(xiàn)這個(gè)虛擬內(nèi)存沒有映射到物理內(nèi)存, CPU 就會(huì)產(chǎn)生缺頁中斷,進(jìn)程會(huì)從用戶態(tài)切換到內(nèi)核態(tài),并將缺頁中斷交給內(nèi)核的 Page Fault Handler (缺頁中斷函數(shù))處理。

        缺頁中斷處理函數(shù)會(huì)看是否有空閑的物理內(nèi)存:

        • 如果有,就直接分配物理內(nèi)存,并建立虛擬內(nèi)存與物理內(nèi)存之間的映射關(guān)系。
        • 如果沒有空閑的物理內(nèi)存,那么內(nèi)核就會(huì)開始進(jìn)行回收內(nèi)存的工作,如果回收內(nèi)存工作結(jié)束后,空閑的物理內(nèi)存仍然無法滿足此次物理內(nèi)存的申請(qǐng),那么內(nèi)核就會(huì)放最后的大招了觸發(fā) OOM (Out of Memory)機(jī)制。

        32 位操作系統(tǒng)和 64 位操作系統(tǒng)的虛擬地址空間大小是不同的,在 Linux 操作系統(tǒng)中,虛擬地址空間的內(nèi)部又被分為內(nèi)核空間和用戶空間兩部分,如下所示:

        通過這里可以看出:

        • 32位系統(tǒng)的內(nèi)核空間占用1G,位于最高處,剩下的3G是用戶空間;
        • 64位系統(tǒng)的內(nèi)核空間和用戶空間都是128T,分別占據(jù)整個(gè)內(nèi)存空間的最高和最低處,剩下的中間部分是未定義的。

        現(xiàn)在可以回答這個(gè)問題了:在 32 位操作系統(tǒng)、4GB 物理內(nèi)存的機(jī)器上,申請(qǐng) 8GB 內(nèi)存,會(huì)怎么樣?

        因?yàn)?32 位操作系統(tǒng),進(jìn)程最多只能申請(qǐng) 3 GB 大小的虛擬內(nèi)存空間,所以進(jìn)程申請(qǐng) 8GB 內(nèi)存,在申請(qǐng)?zhí)摂M內(nèi)存階段就會(huì)失?。ㄎ沂稚蠜]有 32 位操作系統(tǒng)測(cè)試,我估計(jì)失敗的原因是 OOM)。

        在 64 位操作系統(tǒng)、4GB 物理內(nèi)存的機(jī)器上,申請(qǐng) 8G 內(nèi)存,會(huì)怎么樣?

        64 位操作系統(tǒng),進(jìn)程可以使用 128 TB 大小的虛擬內(nèi)存空間,所以進(jìn)程申請(qǐng) 8GB 內(nèi)存是沒問題的,因?yàn)檫M(jìn)程申請(qǐng)內(nèi)存是申請(qǐng)?zhí)摂M內(nèi)存,只要不讀寫這個(gè)虛擬內(nèi)存,操作系統(tǒng)就不會(huì)分配物理內(nèi)存。

        我們可以簡(jiǎn)單做個(gè)測(cè)試,我的服務(wù)器是 64 位操作系統(tǒng),但是物理內(nèi)存只有 2 GB。

        現(xiàn)在,我在機(jī)器上,申請(qǐng) 4 GB 內(nèi)存,注意下面代碼只是單純分配了虛擬內(nèi)存,并沒有使用該虛擬內(nèi)存:


        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <sys/types.h>
        #include <string.h>

        int main() {
            int ret;
            char* addr[4];
            printf("使用cat /proc/%d/maps查看內(nèi)存分配\n",getpid());
            size_t s = 1024 * 1024 * 1024;
            int i = 0;
            for(i = 0; i < 4; ++i) {
                printf("alloc size = %d\n", s);
                addr[i] = (char*) malloc(s);
                printf("主線程調(diào)用malloc后,申請(qǐng)1gb大小得內(nèi)存,此內(nèi)存起始地址:0X%x\n", addr[i]);
            }
            getchar();
            return 0;
        }

        然后運(yùn)行這個(gè)代碼,可以看到,我的物理內(nèi)存雖然只有 2GB,但是程序正常分配了 4GB 大小的虛擬內(nèi)存

        我們可以通過下面這條命令查看進(jìn)程的虛擬內(nèi)存大?。?/p>


        # ps aux | grep alloc_4g
        USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
        root      7797  0.0  0.0 4198540  352 pts/1    S+   16:58   0:00 ./alloc_4g

        其中,VSZ 就代表進(jìn)程使用的虛擬內(nèi)存大小,RSS 代表進(jìn)程使用的物理內(nèi)存大小。可以看到,VSZ 大小為 4198540,也就是 4GB 的虛擬內(nèi)存。

        然后,我們改一下代碼,在申請(qǐng)完虛擬內(nèi)存后,通過 memset 函數(shù)使用這個(gè)虛擬內(nèi)存,看看會(huì)發(fā)生什么。


        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <sys/types.h>
        #include <string.h>

        int main() {
            int ret;
            char* addr[4];
            printf("使用cat /proc/%d/maps查看內(nèi)存分配\n",getpid());
            size_t s = 1024 * 1024 * 1024;
            int i = 0;
            for(i = 0; i < 4; ++i) {
                printf("alloc size = %d\n", s);
                addr[i] = (char*) malloc(s);
                printf("主線程調(diào)用malloc后,申請(qǐng)1gb大小得內(nèi)存,此內(nèi)存起始地址:0X%x\n", addr[i]);
                //訪問虛擬內(nèi)存
                memset(addr[i], 0, s);
            }
            getchar();
            return 0;
        }

        運(yùn)行結(jié)果:

        可以看到,在申請(qǐng)了 2GB 虛擬內(nèi)存后,然后馬上使用了這塊虛擬內(nèi)存,由于這臺(tái)機(jī)器的物理內(nèi)存只有 2 GB,所以發(fā)生了 OOM。

        至此, 驗(yàn)證完成了。簡(jiǎn)單總結(jié)下:

        • 在 32 位操作系統(tǒng),因?yàn)檫M(jìn)程最大只能申請(qǐng) 3 GB 大小的虛擬內(nèi)存,所以直接申請(qǐng) 8G 內(nèi)存,會(huì)申請(qǐng)失敗。
        • 在 64位 位操作系統(tǒng),因?yàn)檫M(jìn)程最大只能申請(qǐng) 128 TB 大小的虛擬內(nèi)存,即使物理內(nèi)存只有 4GB,申請(qǐng) 8G 內(nèi)存也是沒問題,因?yàn)樯暾?qǐng)的內(nèi)存是虛擬內(nèi)存,等這塊虛擬內(nèi)存被訪問了,因?yàn)槲锢砜臻g不夠,就會(huì)發(fā)生 OOM。

        ??????????

        贈(zèng)書福利來襲啦

        Java 誕生 27 年來,這本享譽(yù)全球的 Java 經(jīng)典著作《Core Java》一路伴隨著 Java 的成長(zhǎng),得到了百萬 Java 開發(fā)者的青睞,幾乎出現(xiàn)在每個(gè)“學(xué)Java要看什么書”類似的書單里,影響了幾代技術(shù)人

        27年間,每當(dāng) Java 有新的 LTR 版本發(fā)布,這本書都會(huì)隨之更新,這次也不例外。現(xiàn)在,針對(duì) Java 17 新特性的《Java核心技術(shù)》第 12 版*中文版(卷1)終于上市了!

        《Java核心技術(shù)》第 12 版涵蓋了 Java 17 的最新特性,相應(yīng)調(diào)整了部分內(nèi)容結(jié)構(gòu),同時(shí)延續(xù)之前版本的優(yōu)良傳統(tǒng),利用清晰明了的示例加以解釋,并提供了全部示例代碼,以便讀者學(xué)習(xí)和靈活應(yīng)用。它將續(xù)寫從前的輝煌,使開發(fā)者能及時(shí)跟上 Java 前進(jìn)的步伐

        截止時(shí)間:2022 年 6 月 21 日 16:00  整  
         兌獎(jiǎng)時(shí)間:2022 年 6 月 22 日 16:00截止 

        #留言有禮# 以上的書你喜歡嗎?分享一下你想要這本書的理由!或者你對(duì)本文的見解,活動(dòng)截止時(shí)小編選出10位幸運(yùn)小錦鯉,中獎(jiǎng)?wù)呖色@得實(shí)體書籍一本,我們包郵贈(zèng)送~

             

        1、拖動(dòng)文件就能觸發(fā)7-Zip安全漏洞,波及所有版本

        2、進(jìn)程切換的本質(zhì)是什么?

        3、一次 SQL 查詢優(yōu)化原理分析:900W+ 數(shù)據(jù),從 17s 到 300ms

        4、Redis數(shù)據(jù)結(jié)構(gòu)為什么既省內(nèi)存又高效?

        5、IntelliJ IDEA快捷鍵大全 + 動(dòng)圖演示

        6、全球第三瀏覽器,封殺中國(guó)用戶這種操作!

        點(diǎn)分享

        點(diǎn)收藏

        點(diǎn)點(diǎn)贊

        點(diǎn)在看

        瀏覽 31
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 色一炮| 国产又爽又黄无码无遮挡在线观看 | 女人扒开屁股让男人桶 | 3d黄色片 | 日本高清黄色视频 |