linux 程序存儲時和運行時的結構

前言

看了些Linux內存管理的文章,寫一寫加深對內存管理的印象。

正文

程序的存儲

ELF是Linux的主要可執行文件格式。ELF文件由4部分組成,分別是ELF頭(ELF header)、程序頭表(Program header table)、節(Section)和節頭表(Section header table)。具體如下:

  1. Program header描述的是一個段在文件中的位置、大小以及它被放進內存後所在的位置和大小。即要加載的信息;
  2. Sections保存着object 文件的信息,從連接角度看:包括指令,數據,符號表,重定位信息等等。在圖中,我們可以看到Sections中包括:
    1. text 文本結 存放指令;
    2. rodata 數據結 readonly;
    3. data 數據結 可讀可寫;
  3. Section頭表(section header table)包含了描述文件sections的信息。每個section在這個表中有一個入口;每個入口給出了該section的名字,大小,等等信息。相當於 索引!
    在這裏插入圖片描述

代碼編譯和存儲

在這裏插入圖片描述
在這裏插入圖片描述

Linux 虛擬地址空間如何分佈?

Linux 使用虛擬地址空間,大大增加了進程的尋址空間,由低地址到高地址分別爲:

  1. 只讀段:該部分空間只能讀,不可寫;(包括:代碼段、rodata 段(C常量字符串和#define定義的常量) )
  2. 數據段:保存全局變量、靜態變量的空間;
  3. 堆 :就是平時所說的動態內存, malloc/new 大部分都來源於此。其中堆頂的位置可通過函數 brk 和 sbrk 進行動態調整。
  4. 文件映射區域:如動態庫、共享內存等映射物理空間的內存,一般是 mmap 函數所分配的虛擬地址空間。
  5. 棧:用於維護函數調用的上下文空間,一般爲 8M ,可通過 ulimit –s 查看。
  6. 內核虛擬空間:用戶代碼不可見的內存區域,由內核管理(頁表就存放在內核虛擬空間)。
    下圖是 32 位系統典型的虛擬地址空間分佈(來自《深入理解計算機系統》)。
    在這裏插入圖片描述
    在這裏插入圖片描述

char *a 與char a[] 的區別

char *d = “hello” 中的d是指向第一個字符‘h’的一個指針;char s[20] = “hello” 中數組名s也是指向第一個字符’h’的指針。現執行下列操作:strcat(d, s)。把字符串加到指針所指的字串上去,出現段錯誤。本質原因:*d="hello"存放在常量區,是無法修的。而數組是存放在棧中,是可以修改的。
兩者區別如下:
讀寫能力:char *a = "abcd"此時"abcd"存放在常量區。通過指針只可以訪問字符串常量,而不可以改變它。而char a[20] = “abcd”; 此時 "abcd"存放在棧。可以通過指針去訪問和修改數組內容。

賦值時刻:char *a = "abcd"是在編譯時就確定了(因爲爲常量)。而char a[20] = “abcd”; 在運行時確定

存取效率:char *a = “abcd”; 存於靜態存儲區。在棧上的數組比指針所指向字符串快。因此慢,而char a[20] = "abcd"存於棧上,快。
另外注意:char a[] = “01234”,雖然沒有指明字符串的長度,但是此時系統已經開好了,就是大小爲6-----‘0’ ‘1’ ‘2’ ‘3’ ‘4’ ‘5’ ‘\0’,(注意strlen(a)是不計’\0’)

結束

初步瞭解了程序的存儲結構和運行結構。分享給和我一樣還不太瞭解的朋友。一步一個腳印 . . .

參考:

linux環境內存分配原理 mallocinfo
Linux系統內存管理
Linux內存管理(最透徹的一篇)
Linux C 內存管理
深入理解C語言內存管理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章