天天看點

Linux記憶體--虛拟記憶體,buffer/cacheLinux記憶體相關

Linux記憶體相關

Linux記憶體--虛拟記憶體,buffer/cacheLinux記憶體相關

上圖是32位的作業系統的位址空間情況。

申請虛拟記憶體

首先擷取尋址大小:檢視cat /proc/cpuinfo

[email protected]:~$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 79
model name      : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
stepping        : 1
microcode       : 0xb00002c
cpu MHz         : 2100.000
cache size      : 20480 KB
physical id     : 0
siblings        : 16
core id         : 0
cpu cores       : 8
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 20
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb invpcid_single intel_pt ibrs ibpb stibp kaiser tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm arat pln pts
bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass
bogomips        : 4190.67
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:
           

由上圖可知:

address sizes : 46 bits physical, 48 bits virtual

48位虛拟位址空間,是以可尋址範圍2^48, 核心空間和使用者空間各占一半;是以使用者空間可連續malloc的大小為(2^48)/2 = 2^47 = 2^10 * 2^10 * 2^10 * 2^17

那麼我們通過一個例子來進行驗證(使用malloc進行虛拟位址的申請,看我們最多能申請多少大小的空間):

測試代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{

    unsigned long long mem_size = (unsigned long long)(1024*1024*1024)*1;//1G
    printf("mem_size: %llu\n",mem_size);

    int i = 0;
    while(1) {
        i++;
        int* p_malloc;
        p_malloc = (int*)malloc(mem_size);
        printf("p_malloc: %p\n",p_malloc);
        printf("i: %d\n", i);

    }
    return 0;
}

           

[email protected]:~/sunrise/C++/memory_demo$ gcc main_virtual_address.c -o virtual_address

[email protected]:~/sunrise/C++/memory_demo$ ./virtual_address

i: 131070

p_malloc: 0x7fff681fb010

*p_malloc: 0

i: 131071

p_malloc: 0x7fffa821c010

*p_malloc: 0

i: 131072

p_malloc: (nil)

Segmentation fault (core dumped)

可以看到當malloc申請到131072G的時候,malloc出錯(超過了可申請的範圍);2^17 = 131072

得到總結:

1、malloc是申請連續的虛拟位址空間。

2、虛拟位址可申請的空間,由虛拟位址可尋址範圍确認(48 bits virtual)。

3、malloc隻是申請虛拟位址空間,并沒有真正的使用到實體記憶體,需要memset才會真正和實體記憶體建立真正的映射。

buffer/cache

Linux記憶體--虛拟記憶體,buffer/cacheLinux記憶體相關
Linux記憶體--虛拟記憶體,buffer/cacheLinux記憶體相關

程序讀寫磁盤檔案,會使該區域增加;

app <-> buffer/cache <-> disk

應用讀取檔案:

先讀取cache區域,若存在,則傳回,若不存在,則直接讀取disk内容(同時将内容緩存到cache區域)

應用寫檔案:

将内容寫入buffer,背景線程定時去将buffer回寫到disk。

緩存機制優點:減少系統調用次數,降低CPU上下文切換和磁盤通路頻率。

緩存(cached)是把讀取過的資料儲存起來,重新讀取時若命中(找到需要的資料)就不要去讀硬碟了,若沒有命中就讀硬碟。其中的資料會根據讀取頻率進行組織,把最頻繁讀取的内容放在最容易找到的位置,把不再讀的内容不斷往後排,直至從中删除。

緩沖(buffers)是根據磁盤的讀寫設計的,把分散的寫操作集中進行,減少磁盤碎片和硬碟的反複尋道,進而提高系統性能。linux有一個守護程序定期清空緩沖内容(即寫入磁盤),也可以通過sync指令手動清空緩沖。舉個例子吧:我這裡有一個ext2的U盤,我往裡面cp一個3M的MP3,但U盤的燈沒有跳動,過了一會兒(或者手動輸入sync)U盤的燈就跳動起來了。解除安裝裝置時會清空緩沖,是以有些時候解除安裝一個裝置時要等上幾秒鐘。

讀取檔案

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

int main()
{
    char buf_r[1024];
    int size;
    int fd = open("/home/yms/test/mdc_syslog0.log",O_RDWR);// 該檔案為960M,運作完該程式,buffer/cache大小會增加960M
    if (fd == -1) {
        printf("error open file");
    }else {
        while ((size = read( fd, buf_r, 1024))>0) { // 讀取普通檔案,首次運作,從磁盤中擷取,并将其寫入到cache中,再次讀取時,則從cache中讀取
            printf("read form file:%s OK\n",buf_r);
        }
    }
    close(fd);

    while(1) {
    }

    return 0;
}
           

編譯及運作

gcc buffer_cache_demo.c -o buffer_cache_demo

./buffer_cache_demo

運作的同時,檢視記憶體占用(top 或者 free)

top資訊(運作前):

top - 06:35:46 up 52 days, 3:39, 48 users, load average: 0.00, 0.07, 0.07

Tasks: 582 total, 1 running, 456 sleeping, 121 stopped, 4 zombie

%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 128541.3+total, 127718.5+free, 539.234 used, 283.520 buff/cache

MiB Swap: 1950.992 total, 1132.133 free, 818.859 used. 127381.5+avail Mem

運作後

top - 06:44:10 up 52 days, 3:48, 48 users, load average: 1.04, 0.64, 0.31

Tasks: 582 total, 2 running, 455 sleeping, 121 stopped, 4 zombie

%Cpu(s): 3.1 us, 0.0 sy, 0.0 ni, 96.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 128541.3+total, 126775.3+free, 539.242 used, 1226.777 buff/cache

MiB Swap: 1950.992 total, 1132.219 free, 818.773 used. 127291.9+avail Mem

再次運作:

top - 06:49:07 up 52 days, 3:53, 48 users, load average: 0.44, 0.47, 0.33

Tasks: 584 total, 2 running, 457 sleeping, 121 stopped, 4 zombie

%Cpu(s): 3.1 us, 0.0 sy, 0.0 ni, 96.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 128541.3+total, 126775.7+free, 538.625 used, 1226.984 buff/cache

MiB Swap: 1950.992 total, 1132.285 free, 818.707 used. 127292.4+avail Mem

手動清除緩存:

釋放緩存區記憶體的方法

1)清理pagecache(頁面緩存)

[[email protected] ~]# echo 1 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=1

2)清理dentries(目錄緩存)和inodes

[[email protected] ~]# echo 2 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=2

3)清理pagecache、dentries和inodes

[[email protected] ~]# echo 3 > /proc/sys/vm/drop_caches 或者 # sysctl -w vm.drop_caches=3

上面三種方式都是臨時釋放緩存的方法,要想永久釋放緩存,需要在/etc/sysctl.conf檔案中配置:vm.drop_caches=1/2/3,然後sysctl -p生效即可!

手動執行完上面三個清除動作後的top資訊

top - 06:50:43 up 52 days, 3:54, 48 users, load average: 0.69, 0.58, 0.39

Tasks: 584 total, 1 running, 458 sleeping, 121 stopped, 4 zombie

%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 128541.3+total, 127723.4+free, 541.965 used, 275.934 buff/cache

MiB Swap: 1950.992 total, 1132.305 free, 818.688 used. 127382.3+avail Mem

繼續閱讀