日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux02进程内存管理

發布時間:2023/11/30 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux02进程内存管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.進程地址空間

? ?1.1程序的結構與進程的結構

? ? ? ?[root@localhost demo]# size test


? text ? data ? ?bss ? ?dec ? ?hex filename

? ? 1193 ? ?492 ? ? 16 ? 1701 ? ?6a5 test

? ? ? ? 一個可執行程序包含三個部分:

? ? ? ? 代碼段:主要存放指令,操作以及只讀的常量數據例如字符串常量。

? ? ? ? 數據段:全局或者靜態的已經初始化的變量

? ? ? ? BSS段:全局或者靜態的未初始化的變量

? ? ? ? 執行一個程序要運行,需要將程序加載到內存(磁盤有專門的讀寫驅動,但是速度比較慢,內存可有cpu直接訪問讀寫,比磁盤速度要快)

? ?

名稱速度
CPU寄存器1ns
cache1ns~10ns
DRAM100ns
磁盤10ss
? ? ? 進程:進程是操作系統最小的資源管理單元。一個程序運行,必然要為其創建一個進程有生命周期的。一個進程是執行的程序段。

? ? ? ? ? ? ? ? 其資源分為內核資源和用戶資源。內核資源是PCB---進程控制塊,也就是一個結構體,負責管理進程所有資源。

? ? ? ? ? ? ? ? mm_struct指向該進程相關的內存資源:從低到高地址分為:代碼段->數據段->BSS段->堆段->棧段

? ? ? ? ? ? ? ? 在執行程序時,系統首先在內核空間創建一個進程,為這個進程申請一個進程控制塊PCB(task_struct),用于管理整個進城的所有資源。

? ?? 代碼段,數據段,BSS段,直接從磁盤拷貝到當前內存空間,大小相等。

? ?? 動態的空間:堆和棧空間,以及mmap段(主要是映射其他庫的相關信息)

? ? ? ? ? ? ? ? 命令:pmap 進程號或者cat /proc/進程號/maps

? ? ? ? ? ? ? ? ? ? ? ?[root@localhost proc]# cat 31281/maps
00400000-004d4000 r-xp 00000000 08:02 390951 ? ? ? ? ? ? ? ? ? ? ? ? ? ? /bin/bash
006d3000-006dd000 rw-p 000d3000 08:02 390951 ? ? ? ? ? ? ? ? ? ? ? ? ? ? /bin/bash
006dd000-006e2000 rw-p 00000000 00:00 0?
008dc000-008e5000 rw-p 000dc000 08:02 390951 ? ? ? ? ? ? ? ? ? ? ? ? ? ? /bin/bash
00b45000-00ba8000 rw-p 00000000 00:00 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?[heap]
32c0c00000-32c0c20000 r-xp 00000000 08:02 781828 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/ld-2.12.so
32c0e1f000-32c0e20000 r--p 0001f000 08:02 781828 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/ld-2.12.so
32c0e20000-32c0e21000 rw-p 00020000 08:02 781828 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/ld-2.12.so
32c0e21000-32c0e22000 rw-p 00000000 00:00 0?
32c1000000-32c1002000 r-xp 00000000 08:02 782740 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libdl-2.12.so
32c1002000-32c1202000 ---p 00002000 08:02 782740 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libdl-2.12.so
32c1202000-32c1203000 r--p 00002000 08:02 782740 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libdl-2.12.so
32c1203000-32c1204000 rw-p 00003000 08:02 782740 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libdl-2.12.so
32c1400000-32c158b000 r-xp 00000000 08:02 782725 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libc-2.12.so
32c158b000-32c178a000 ---p 0018b000 08:02 782725 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libc-2.12.so
32c178a000-32c178e000 r--p 0018a000 08:02 782725 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libc-2.12.so
32c178e000-32c178f000 rw-p 0018e000 08:02 782725 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libc-2.12.so
32c178f000-32c1794000 rw-p 00000000 00:00 0?
3e6a000000-3e6a01d000 r-xp 00000000 08:02 781958 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libtinfo.so.5.7
3e6a01d000-3e6a21c000 ---p 0001d000 08:02 781958 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libtinfo.so.5.7
3e6a21c000-3e6a220000 rw-p 0001c000 08:02 781958 ? ? ? ? ? ? ? ? ? ? ? ? /lib64/libtinfo.so.5.7
3e6a220000-3e6a221000 rw-p 00000000 00:00 0?
7f2a4f326000-7f2a551b7000 r--p 00000000 08:02 914111 ? ? ? ? ? ? ? ? ? ? /usr/lib/locale/locale-archive
7f2a551b7000-7f2a551c3000 r-xp 00000000 08:02 781857 ? ? ? ? ? ? ? ? ? ? /lib64/libnss_files-2.12.so
7f2a551c3000-7f2a553c3000 ---p 0000c000 08:02 781857 ? ? ? ? ? ? ? ? ? ? /lib64/libnss_files-2.12.so
7f2a553c3000-7f2a553c4000 r--p 0000c000 08:02 781857 ? ? ? ? ? ? ? ? ? ? /lib64/libnss_files-2.12.so
7f2a553c4000-7f2a553c5000 rw-p 0000d000 08:02 781857 ? ? ? ? ? ? ? ? ? ? /lib64/libnss_files-2.12.so
7f2a553c5000-7f2a553c8000 rw-p 00000000 00:00 0?
7f2a553cc000-7f2a553ce000 rw-p 00000000 00:00 0?
7f2a553ce000-7f2a553d5000 r--s 00000000 08:02 914369 ? ? ? ? ? ? ? ? ? ? /usr/lib64/gconv/gconv-modules.cache
7f2a553d5000-7f2a553d6000 rw-p 00000000 00:00 0?
7fffc0a71000-7fffc0a86000 rw-p 00000000 00:00 0 ? ? ? ? ? ? ? ? ? ? ? ? ?[stack]

7fffc0b0a000-7fffc0b0b000 r-xp 00000000 00:00 0 ? ? ? ? ? ? ? ? ? ? ? ? ?[vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 ? ? ? ? ? ? ? ? ?[vsyscall]

? ? ? ? ? ? ? ? ?所看到的地址不是物理地址,都是虛擬地址。出于對資源的保護,一個程序并不需要立即將所有的資源全部加載到內存,而是實際上可采用寫時申請的方法。而且保護系統,很多用戶非法訪問不會造成內核的崩潰。

? ? ?1.2虛擬地址空間的申請

? ? ? ? ? ? ? 32位平臺下,一個進程擁有4G的虛擬地址,這個地址如何來分配和使用呢

  • ?代碼段,數據段,BSS段,這三個部分直接從磁盤拷貝到內存,起始地址在當前的32位平臺下的地址為0x08048000.
  • ?堆棧。是動態變化
  • mmap映射的文件
  • 棧段
  • 高地址1G空間,僅供內核映射處理,用戶空間不能直接處理
    內核空間1G
    gap間隙為了安全
    高地址向低地址增長
    map映射區域
    ?
    gap間隙為了安全
    BSS?
    數據段?
    代碼段?

  • 堆和棧的起始地址是隨機產生的,其目的是為了避免安全漏洞。但是可以指定在堆中申請空間的起始地址(brk/sbrk函數);
    #include<stdio.h>
    #include<stdlib.h>

    #include<stdio.h>
    #include<stdlib.h>


    int main(int argc,char*argv[])
    {
    ? brk(0x09050000);
    ? printf("brk=%p\n",sbrk(0));
    ? char *ptr=malloc(1024);
    ? printf("new=%p\n",ptr);
    ? return 1;
    }
    結果:
  • [root@localhost demo]# ./t
    brk=0x9050000
    new=0x9050010
  • 系統執行一個過程,到底怎么來加載這些空間的?可以用strace工具來查看。
  • ?strace ./t
    execve("./t", ["./t"], [/* 25 vars */]) = 0
    brk(0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x7e0000//起始地址
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb578bba000
    access("/etc/ld.so.preload", R_OK) ? ? ?= -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY) ? ? ?= 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=52315, ...}) = 0
    mmap(NULL, 52315, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb578bad000
    close(3) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0
    open("/lib64/libc.so.6", O_RDONLY) ? ? ?= 3
    read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\356A\3012\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=1926800, ...}) = 0
    mmap(0x32c1400000, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x32c1400000
    mprotect(0x32c158b000, 2093056, PROT_NONE) = 0
    mmap(0x32c178a000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x32c178a000
    mmap(0x32c178f000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x32c178f000
    close(3) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb578bac000
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb578bab000
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb578baa000
    arch_prctl(ARCH_SET_FS, 0x7fb578bab700) = 0
    mprotect(0x32c178a000, 16384, PROT_READ) = 0
    mprotect(0x32c0e1f000, 4096, PROT_READ) = 0
    munmap(0x7fb578bad000, 52315) ? ? ? ? ? = 0
    brk(0x9050000) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x9050000
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb578bb9000
    write(1, "brk=0x9050000\n", 14brk=0x9050000
    ) ? ? ? ? = 14
    brk(0x9071000) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x9071000
    write(1, "new=0x9050010\n", 14new=0x9050010
    ) ? ? ? ? = 14
    exit_group(1) ? ? ? ? ? ? ? ? ? ? ? ? ? = ?
  • 堆空間的起始地址是隨機的,可設置為不隨機。大小也可以設置成固定大小
    代碼段,數據段,BSS段的地址在編譯鏈接時固定
    在BSS結束和堆起始地址有空隙,這個空隙是隨機的
    brk函數僅僅是調整在堆中申請空間的起始值。使用以下命令可以指定堆的起始地址固定
    sudo sysctl -w kernel/randomize_va_space=0


  • 系統默認為每個進程分配的堆空間大小是固定的。使用 sbrk(0)得到的是我們堆空間的結束
    值。第一次使用 malloc 申請資源返回的地址接近于堆空間的起始值。全用 brk(addr)改變的是新申請數據
    的堆空間起始值。
  • 在真正編程中,很少全用 brk/sbrk,使用 malloc函數來新申請堆空間,效率更高。部分時間使
    用 mmap來映射 mmap區,
    棧:棧從高地址向低地址增長,棧的起始值也是隨機的。棧中主要存放的是局部變量,新調用子函
    數時函數的參數及返回值。由 OS自動管理。

1.3內存空間的申請和釋放
  • 代碼段中:由只讀數據和代碼組成: const,字符串常量,這些內容的空間在編譯鏈接時申請好
    且指定存儲地址。
    ?
  • 數據段 BSS 段申請:定義的全局的或者是靜態的變量。已經初始化的在數據段,未初始化的
    BSS段中。因此也是在編譯鏈接時已經申請且指定的地址。
    以上空間的申請在運行時候就加載到內存中,直到程序的結束,不在發生變化,除了exec函數執行
  • 堆:由程序員自己動態管理。
    動態申請,堆的起始位置由brk函數指定,但是具體編程中一般不會自己使用它,而是使用malloc函數。內核對內存的管理是頁式管理,因此在 malloc申請空間時,使用鏈式結構來管理已經
    申請的堆空間。

  • 棧:由os管理
  • mmap的庫以及相關文件
    將一個文件的內容全部或者部分的映射到虛擬地址空間中,后面釋放時操作這段內存空間可以被同
    步到磁盤文件的操作,效率比較高。共享映射,其它進程如果也映射這個文件,可以立即看到這個更改,但并不是立即更新磁盤文件的內容,如果要更新到磁盤,必須使用 msync以及 munmap時。?

2.常見內存錯誤以及valgrind使用

? ? ? ? ?代碼段:只讀數據。因此對這一部分的數據,試圖寫只讀數據。這個在編譯的時候基本可以檢測。

數據段/BSS段:未初始化直接訪問。即使沒有顯式初始化,仍然會初始化為 0。
棧空間數據:
(1)局部變量,未初始化這類變量會給隨機的初值,出現異常情況更詭異。
(2) 棧溢出,在棧中申請過大的局部變量。
堆空間數據:
內存泄漏,( 1)申請未釋放( 2)申請后,雙重釋放。
對于所有的地址空間:
( 1)野指針的問題。未初始化指針。去訪問這個指針指向的空間。
( 2)越界訪問,例如一個數組 a[10],試圖訪問 a[10]以及以后。
( 3)非法的越權訪問。例如 mmap的空間只讀,但試圖寫。
( 4)空間不在控制范圍仍然去訪問空間,例如返回局部變量地址,且后面訪問這個空間。
使用工具,來檢測常見的內存錯誤。 valgrind工具。
1041 gcc -o valgrind_example01 valgrind_example01.c -g
1042 valgrind --tool=memcheck --show-reachable=yes --read-var-info=yes --verbose --time-stamp=yes --
leak-check=full --log-file=mycode.log ./valgrind_example01
1043 less mycode.log
如果要使用圖形化的工具,要安裝 QT,這個工具名字叫 valkyrie。
? ? ? ? ?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Linux02进程内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。