ICS2019大作業--程序人生

 

 

 

 

 

 

 

計算機科學與技術學院

2019年12月

摘  要

摘要是論文內容的高度概括,應具有獨立性和自含性,即不閱讀論文的全文,就能獲得必要的信息。摘要應包括本論文的目的、主要內容、方法、成果及其理論與實際意義。摘要中不宜使用公式、結構式、圖表和非公知公用的符號與術語,不標註引用文獻編號,同時避免將摘要寫成目錄式的內容介紹。

 

關鍵詞:關鍵詞1;關鍵詞2;……;                           

 

(摘要0分,缺失-1分,根據內容精彩稱都酌情加分0-1

 

 

 

 

 

 

 

 

 

目  錄

 

第1章 概述.................................................................................................................. - 4 -

1.1 Hello簡介......................................................................................................................................... - 4 -

1.2 環境與工具..................................................................................................................................... - 4 -

1.3 中間結果.......................................................................................................................................... - 4 -

1.4 本章小結.......................................................................................................................................... - 4 -

第2章 預處理............................................................................................................... - 5 -

2.1 預處理的概念與作用..................................................................................................................... - 5 -

2.2在Ubuntu下預處理的命令........................................................................................................... - 5 -

2.3 Hello的預處理結果解析................................................................................................................ - 5 -

2.4 本章小結.......................................................................................................................................... - 5 -

第3章 編譯.................................................................................................................. - 6 -

3.1 編譯的概念與作用......................................................................................................................... - 6 -

3.2 在Ubuntu下編譯的命令............................................................................................................... - 6 -

3.3 Hello的編譯結果解析.................................................................................................................... - 6 -

3.4 本章小結.......................................................................................................................................... - 6 -

第4章 彙編.................................................................................................................. - 7 -

4.1 彙編的概念與作用......................................................................................................................... - 7 -

4.2 在Ubuntu下彙編的命令............................................................................................................... - 7 -

4.3 可重定位目標elf格式.................................................................................................................. - 7 -

4.4 Hello.o的結果解析......................................................................................................................... - 7 -

4.5 本章小結.......................................................................................................................................... - 7 -

第5章 鏈接.................................................................................................................. - 8 -

5.1 鏈接的概念與作用......................................................................................................................... - 8 -

5.2 在Ubuntu下鏈接的命令............................................................................................................... - 8 -

5.3 可執行目標文件hello的格式...................................................................................................... - 8 -

5.4 hello的虛擬地址空間.................................................................................................................... - 8 -

5.5 鏈接的重定位過程分析................................................................................................................. - 8 -

5.6 hello的執行流程............................................................................................................................. - 8 -

5.7 Hello的動態鏈接分析.................................................................................................................... - 8 -

5.8 本章小結.......................................................................................................................................... - 9 -

第6章 hello進程管理................................................................................................ - 10 -

6.1 進程的概念與作用....................................................................................................................... - 10 -

6.2 簡述殼Shell-bash的作用與處理流程....................................................................................... - 10 -

6.3 Hello的fork進程創建過程......................................................................................................... - 10 -

6.4 Hello的execve過程...................................................................................................................... - 10 -

6.5 Hello的進程執行.......................................................................................................................... - 10 -

6.6 hello的異常與信號處理.............................................................................................................. - 10 -

6.7本章小結........................................................................................................................................ - 10 -

第7章 hello的存儲管理............................................................................................. - 11 -

7.1 hello的存儲器地址空間.............................................................................................................. - 11 -

7.2 Intel邏輯地址到線性地址的變換-段式管理............................................................................ - 11 -

7.3 Hello的線性地址到物理地址的變換-頁式管理....................................................................... - 11 -

7.4 TLB與四級頁表支持下的VA到PA的變換.............................................................................. - 11 -

7.5 三級Cache支持下的物理內存訪問........................................................................................... - 11 -

7.6 hello進程fork時的內存映射..................................................................................................... - 11 -

7.7 hello進程execve時的內存映射.................................................................................................. - 11 -

7.8 缺頁故障與缺頁中斷處理.......................................................................................................... - 11 -

7.9動態存儲分配管理....................................................................................................................... - 11 -

7.10本章小結...................................................................................................................................... - 12 -

第8章 hello的IO管理............................................................................................... - 13 -

8.1 Linux的IO設備管理方法............................................................................................................. - 13 -

8.2 簡述Unix IO接口及其函數......................................................................................................... - 13 -

8.3 printf的實現分析.......................................................................................................................... - 13 -

8.4 getchar的實現分析...................................................................................................................... - 13 -

8.5本章小結........................................................................................................................................ - 13 -

結論............................................................................................................................ - 14 -

附件............................................................................................................................ - 15 -

參考文獻..................................................................................................................... - 16 -

 

 

 

第1章 概述

1.1 Hello簡介

根據Hello的自白,利用計算機系統的術語,簡述Hello的P2P,020的整個過程。

Hello是指名爲“hello”的可執行文件。首先hello的源代碼以C語言文本的形式被程序員輸入電腦,並存儲在名爲“hello.c”的C語言源文件中。其次,程序員通過預處理程序將源文件進行預處理,生成名爲“hello.i”的預處理文件。接着,程序員通過使用編譯器,將“hello.i”進行編譯,將C語言fanyic機器語言,以文本形式存儲在名爲“hello.s”的彙編語言代碼文件中。在這之後,程序員通過使用匯編程序,將“hello.s”從彙編語言翻譯成機器語言,以可重定位目標文件的形式、二進制表示地存儲在“hello.o”中。最後,程序員使用鏈接器,將“hello.o”和其他用到地可重定位目標文件(如預編譯好的庫文件)鏈接在一起,生成名爲“hello”的可執行目標文件,這便是Hello的誕生。

linux環境中,程序員開啓Bash,執行“hello”,OS的進程管理程序就會在Bash中fork一個子進程,通過設置進程組id的方式使這個子進程與Bash進程分離,然後調用execve函數執行“hello”這個可執行目標文件,使用mmap函數進行內存映射以實現高校讀寫或者內存共享,分配給這個子進程時間片來決定它的運行實踐,接着這個子進程就藉助CPU對指令進行取值、譯碼、執行等操作,並藉助流水線機制加快執行速度,在CPU、RAM、IO中進行數據讀寫和運算,最終實現“hello”的執行。

在數據讀寫的具體過程中,OS的存儲管理程序和內存管理單元(MMU)將程序的虛擬內存地址(VA)轉化爲物理內存地址(PA),實現數據存取。爲了提高數據訪問的速度,計算機硬件按照局部性原理,設計了一套多級的存儲結構。系統首先通過TLB查找數據,若存在TLB頁表中,則直接從3級Cache中取出數據;若沒有,則訪問主存中的頁表,若有則訪問數據並更新TLB,若無則引發缺頁異常,從磁盤中找到數據放入主存,同時更新TLB和頁表。

在程序執行的過程中,IO管理程序調度着IO設備間的通信,而信號機制則處理着各種各樣的異常,使程序最終能夠正常執行。

在程序執行結束後,Bash進程會收到SIGCHILD異常,接着調用waitpid函數回收hello進程;若Bash提前終止,那麼hello進程就變成了孤兒進程。這時,OS的__init__進程就會“收養”這個進程,成爲它的養父進程,代爲行使回收hello進程的職責。至此,hello進程實現了它的從program到progress的一生,結束了它的生命週期。

Hello的整個生命週期中,由計算機系統的編輯器以文本形式寫就源代碼,接着分別由Cpp、Compiler、AS、LD分別完成了預處理、編譯、彙編和鏈接,生成可執行目標文件(簡稱可執行文件),在執行時由OS分配虛擬內存空間並映射到物理內存空間、由CPU進行執行,在RAM和IO間進行數據讀寫,最終結束執行後又被父進程或者養父進程回收,釋放自己佔用的資源。縱觀它的整個生命週期,從無中來,到無中去,是爲O2O。這一切,計算機系統(CS)是一切的參與者和見證者。

1.2 環境與工具

列出你爲編寫本論文,折騰Hello的整個過程中,使用的軟硬件環境,以及開發與調試工具。

  1. X64CPU; 2.40GHz; 8G RAM; 1T HD Disk;
  2. Windows10 64位,VMware workstation player 15; Ubuntu 18.04 LTS 64位

1.2.1 硬件環境

  1. X64CPU; 2.40GHz; 8G RAM; 1T HD Disk;

1.2.2 軟件環境

  1. Ubuntu+gcc

1.2.3 開發工具

  1. VScode+gcc

1.3 中間結果

列出你爲編寫本論文,生成的中間結果文件的名字,文件的作用等。

1.4 本章小結

 

(第10.5分)

 

 

 

第2章 預處理

2.1 預處理的概念與作用

預處理是從源程序編程可執行程序的第一步。C預處理程序是cpp(C Preprocessor的縮寫)。這一步是對編譯的準備工作,主要實現對頭文件的包含、宏定義的擴展、條件編譯的選擇等等。

 

2.2Ubuntu下預處理的命令

cpp hello.c -o hello.i

或者

Gcc -E main.c -o hello.i

以下格式自行編排,編輯時刪除

應截圖,展示預處理過程!

2.3 Hello的預處理結果解析

(1)首先,源代碼中的註釋不見了,說明預處理程序刪除了註釋

(2)其次,宏定義也沒有(測試時在源文件中另外添加了一行宏定義語句,而預處理之後不見了),說明預處理程序識別了宏定義並對源代碼進行了相應替換

(3)#include指令被解析了,頭文件被直接插入到了源文件中

2.4 本章小結

 

本章主要探討了預處理的作用。預處理是C語言源文件轉換爲可執行文件的第一步,是對編譯環節的準備工作。這一階段,程序員應使用C預處理程序,將源文件進行預處理,具體工作包括頭文件的插入、註釋的刪除、宏定義的擴展和條件編譯的選擇等等。

 

(第20.5分)

 

第3章 編譯

3.1 編譯的概念與作用

 

編譯是指將經過預處理的源文件轉換爲彙編語言文本文件的過程。

在這個環節,C編譯器會對源程序進行詞法分析和語法分析,根據分析的結果進行代碼優化和存儲分配,最終將其轉換爲彙編語言程序。一次編譯由編譯器通過對源代碼進行多次掃描完成,一次完成其中的幾項任務或者一項任務的某一部分。

注意:這兒的編譯是指從 .i 到 .s 即預處理後的文件到生成彙編語言程序

       

 

3.2 Ubuntu下編譯的命令

ccl hello.i -o hello.s

或者

gcc -S hello.i -o hello.s

另外可以進行參數設置,例如截圖中的那樣

應截圖,展示編譯過程!

3.3 Hello的編譯結果解析

 

首先是代碼hello.s的代碼全覽:

    .file   "hello.c"

    .text

    .section    .rodata.str1.8,"aMS",@progbits,1

    .align 8

.LC0:

    .string "\347\224\250\346\263\225: Hello \345\255\246\345\217\267 \345\247\223\345\220\215 \347\247\222\346\225\260\357\274\201"

    .section    .rodata.str1.1,"aMS",@progbits,1

.LC1:

    .string "Hello %s %s\n"

    .text

    .globl  main

    .type   main, @function

main:

.LFB52:

    .cfi_startproc

    pushq   %rbp

    .cfi_def_cfa_offset 16

    .cfi_offset 6, -16

    pushq   %rbx

    .cfi_def_cfa_offset 24

    .cfi_offset 3, -24

    subq    $8, %rsp

    .cfi_def_cfa_offset 32

    cmpl    $4, %edi

    jne .L6

    movq    %rsi, %rbp

    movl    $0, %ebx

    jmp .L2

.L6:

    movl    $.LC0, %edi

    call    puts

    movl    $1, %edi

    call    exit

.L3:

    movq    16(%rbp), %rcx

    movq    8(%rbp), %rdx

    movl    $.LC1, %esi

    movl    $1, %edi

    movl    $0, %eax

    call    __printf_chk

    movq    24(%rbp), %rdi

    movl    $10, %edx

    movl    $0, %esi

    call    strtol

    movl    %eax, %edi

    call    sleep

    addl    $1, %ebx

.L2:

    cmpl    $7, %ebx

    jle .L3

    movq    stdin(%rip), %rdi

    call    _IO_getc

    movl    $0, %eax

    addq    $8, %rsp

    .cfi_def_cfa_offset 24

    popq    %rbx

    .cfi_def_cfa_offset 16

    popq    %rbp

    .cfi_def_cfa_offset 8

    ret

    .cfi_endproc

.LFE52:

    .size   main, .-main

    .ident  "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"

    .section    .note.GNU-stack,"",@progbits

 

3.3.1 整型常量定義

                 觀察源文件“hello.c”,發現共有8個整型數值常量,分別是:

  1. 用於判斷參數個數的整型常量“4”
  2. 用於指示程序結束狀態的狀態碼整型常量“1”和“0”
  3. 用於變量賦值的整形常量“0”
  4. 用於循環計數的整形常量“8”
  5. 用於指示參數數組argv索引的“1”、“2”和“3”

 

其中,(1)、(2)、(3)是以立即數的形式直接出現在彙編語言程序的代碼段的。

 

針對(4),它並沒有顯式地出現在代碼中,分析後發現,由於它的作用是限制循環的次數,當循環次數小於它時退出循環,所以編譯器將這部分優化成讓循環次數與“7”相比較,使用“jle”命令實現跳轉。

 

類似地,(5)也沒有顯式的出現在代碼中,它們是argv數組的索引,而argv是字符串數組,其元素是地址,大小是固定的8個字節,因此這三個索引被優化成地址的索引,分別是argv的地址加8個字節、16個字節和24個字節

3.3.2 局部整型變量定義

         代碼中有兩個整型變量,一個是作爲函數入口參數的,指明參數字符串組元素個數的argc,另一個是用於循環計數的整型變量i

Argc由於是函數參數,所以按照規範存儲在寄存器edi中;i是變量,分析彙編代碼後發現,編譯器用寄存器ebx表示和存儲i的值。

3.3.3 字符串常量定義

源代碼中有兩個字符串常量,分別是用於標準輸出的字符串常量

"用法: Hello 學號 姓名 秒數!\n"

       以及用於格式化輸出的字符串常量

"Hello %s %s\n"

它們都定義在了彙編代碼的只讀數據段,如下面所示:

    .section    .rodata.str1.8,"aMS",@progbits,1

    .align 8

.LC0:

    .string "\347\224\250\346\263\225: Hello \345\255\246\345\217\267 \345\247\223\345\220\215 \347\247\222\346\225\260\357\274\201"

    .section    .rodata.str1.1,"aMS",@progbits,1

.LC1:

    .string "Hello %s %s\n"

3.3.4 變量的聲明和賦初值

Argc由於是父進程賦值,所以這裏討論i。從彙編代碼中,程序開始時進行了將寄存器rbx入棧保存的操作:

pushq  %rbx

這可以看作是對變量i的聲明

而後,程序用movl命令對變量i進行了賦初值操作:

movl   $0, %ebx

3.3.5 類型轉換

代碼中不存在隱式的類型轉換操作,但存在一處顯式的類型轉換:

參數字符串組的第4個元素指明瞭sleep函數的參數,需要使用atoi函數將它從字符串轉化爲整型數值,這部分的彙編代碼如下:

    movq    24(%rbp), %rdi

    movl    $10, %edx

    movl    $0, %esi

    call    strtol

可以看到,首先,使用movq指令和寄存器間接尋址,將argv[3]的數據傳給寄存器rdi,那麼rdi中所儲存的值就是所調用函數的第一個參數的值;接着,調用movl命令分別給寄存器esi和edx賦值爲0和10,它們分別是所調用函數的第二個和第三個參數;最後,利用call命令調用方函數strtol。整個調用過程代表用strtol函數按照十進制將字符串轉換爲數字。也即是說,雖然我們調用的函數是atoi,但是底層是通過strtol函數實現的,函數atoi是函數strtol的一個特例。

3.3.6 算數操作

         代碼中只有一種算數操作,那便是用於循環計數的自增運算:

for(i=0;i<8;i++){

在彙編語言代碼中,i的自增運算是同過addl命令給代表i的寄存器的值加上立即數$1完成的:

addl   $1, %ebx

 

 

 

                 此部分是重點,說明編譯器是怎麼處理C語言的各個數據類型以及各類操作的。應分3.3.1~ 3.3.x等按照類型和操作進行分析,只要hello.s中出現的屬於大作業PPT中P4給出的參考C數據與操作,都應解析

3.3.7  關係操作

  代碼中只有一種關係操作,那便是檢查參數數量是否滿足要求的“!=”:

         if(argc!=4){

在彙編語言代碼中,是通過cmpl命令實現的:

cmpl   $4, %edi

3.3.8  數組操作:

代碼中存在一個數組:參數字符串數組“argv”,由於argv是字符串的數組,因此它的每個元素大小相等,都是某個字符串的首地址。由於我們是按照64位編譯的,因此每個地址的大小是8個字節。也就是說,元素argv[i]的地址就是argv的地址加上i個8的值。例如:

movq   16(%rbp), %rcx

    movq    8(%rbp), %rdx

    movl    $.LC1, %esi

    movl    $1, %edi

    movl    $0, %eax

    call    __printf_chk

    movq    24(%rbp), %rdi

上面的這段代碼中,分別出現了16(%rbp)、8(%rbp)、24(%rbp),它們分別是argv[2]、argv[1]、argv[3]

3.3.9  控制轉移

代碼中共出現了兩次控制轉移,一次是if語句引起的控制轉移,另一次是for語句引起的控制轉移:

if(argc!=4){

for(i=0;i<8;i++){

 

  1. 針對if語句,代碼中是通過cmpl命令和jne命令合作實現的:

cmpl   $4, %edi

    jne .L6

這兩句話的意思是,將立即數4的大小與寄存器edi中存儲的數的大小相比,如果不相等的話,就跳轉到.L6代碼段,否則繼續按順序執行接下來的代碼

  1. 針對for語句,代碼中分成了下面幾個部分:
    1. 首先是給循環計數變量初始化爲0:

movl   $0, %ebx

    jmp .L2

現在跳轉到.L2代碼段

    1. 接下來是比較循環計數變量與7的大小:

                  .L2:

           cmpl    $7, %ebx

           jle .L3

                若是小於或者等於7的話,跳轉到.L3代碼段:

    1. 下面是計數器變量的自增操作:

.L3:

    movq    16(%rbp), %rcx

    movq    8(%rbp), %rdx

    …  …

addl    $1, %ebx

.L2:

    cmpl    $7, %ebx

    jle .L3

…  …

                可見,通過調用addl命令,將寄存器ebx存儲的值增加1

    1. 從上面的代碼段可以看出,.L3代碼段和.L2代碼段是相鄰的,而且.L2代碼段在.L3代碼段的下面。按照順序執行的原則,接下來就將再次將寄存器ebx存儲的值與7相比並決定是否跳轉。

至此,整個循環構造完成。我們同時可以看出來,原來是看i的值是否小於8相比並決定是否跳轉,現在則是與7相比,觀察它們是不是小於等於的關係,兩者實際上是等價的。

3.3.10       函數操作

在C語言代碼中,共有5個函數:main、printf、atoi、sleep、getchar、exit

而在彙編代碼中兩處printf函數被分別轉化爲了puts函數和__printf_chk函數,atoi函數被轉化爲了strtol函數,getchar函數被轉化爲了_IO_getc函數,其他的函數還是原來的名字。下面,分別從參數傳遞、函數調用和函數返回三方面進行分析:

  1. 參數傳遞:

在存在多個參數的情況下,寄存器rdi、rsi、rdx、rcx分別被用來傳遞第一個、第二個、第三個和第四個參數,例如:

  1. 在main函數剛開始時,edi中的值便是argc的值,而rsi中的值,便是argv字符串數組的首地址
  2. 在puts函數調用時:

movl   $.LC0, %edi

  call    puts

先把.LC0的值傳給edi作爲puts函數的第一個參數,而.LC0是定義在只讀數據區的字符串(string)

  1. 在__printf_chk函數被調用時:

movq   16(%rbp), %rcx

     movq    8(%rbp), %rdx

    movl    $.LC1, %esi

    movl    $1, %edi

    movl    $0, %eax

    call    __printf_chk

 可見,第一個參數是立即數1,第二個參數是.LC1,它和.LC0一樣,是定義在只讀數據區的字符串常量。第三個參數是argv[1]的值,它是字符串數組的第二個元素,是某個字符串的首地址。同樣地,第四個參數是argv[2]的值,字符串數組的第三個元素。

  1. 在strtol函數被調用時:

movq   24(%rbp), %rdi

movl    $10, %edx

movl    $0, %esi

call    strtol

第一個參數是argv[3],它是字符串數組的第四個元素,是某一個字符串的首地址。第二個參數是立即數0,它是字符串結束的標誌。第三個參數是10,他表示將字符串按照十進制數字解讀

  1. 在sleep函數被調用時:

call   strtol

movl    %eax, %edi

call    sleep

eax寄存器存儲的是函數的返回值,剛掉用過strtol函數,因此將eax存儲的值賦值給edi,再調用sleep函數,就是將strtol函數的返回值作爲唯一的參數傳遞給sleep

  1. 在調用__IO_getc函數時:

movq   stdin(%rip), %rdi

  call    _IO_getc

可以看到,rdi中存儲的是標準輸入流的描述符,即該函數唯一的參數便是標準輸入流

  1. 在調用exit函數時:

movl   $1, %edi

  call    exit

寄存器edi中存儲的值是立即數1,也就是將整型數字1作爲唯一的參數傳給函數exit

  1. 函數調用

從上面的分析中可以看出,在參數就位後,使用call命令就可以實現函數的調用

(3)函數返回

分析代碼可以發現,函數返回是通過ret命令實現的,返回值存儲寄存器eax中

3.4 本章小結

 

本章我們探索了編譯的概念、作用、方法和結果。

編譯是指使用編譯器將預處理文件經過分析,進行代碼優化和存儲分配,最終轉化爲彙編語言代碼文件的過程。編譯可以將C語言轉化爲與機器緊密相關的機器語言,從而使代碼能夠在對應機器上運行。Linux環境下常常使用gcc -S命令或者cpp命令進行編譯工作。

在本章中,我們重點分析了編譯的結果,討論了編譯器對各種操作在機器語言上的實現方式,包括數據定義與賦值、類型轉換、算術操作、關係操作、數組操作、控制轉移和函數操作,進一步體會了編譯的實際工作。

(第32分)

 

第4章 彙編

4.1 彙編的概念與作用

 

彙編是指將編譯生成的彙編語言代碼轉換爲機器語言代碼,生成可重定位目標文件。每個模塊都生成一個可重定位目標文件,若最終的程序有多個模塊組成,那麼這一步將生成多個可重定位目標文件。

 

注意:這兒的彙編是指從 .s 到 .o 即編譯後的文件到生成機器語言二進制程序的過程。

4.2 Ubuntu下彙編的命令

使用

gcc -c main.s -o main.o

或者

as main.s -o main.o

編譯結果如下:

4.3 可重定位目標elf格式

分析hello.o的ELF格式,用readelf等列出其各節的基本信息,特別是重定位項目分析。

ELF格式的全稱是Executable and Linkable Format,即可執行可鏈接格式,是現代UNIX操作系統主要使用的目標文件格式。Hello.o屬於可重定位目標文件,主要包含代碼部分和數據部分,可以與其他可重定位目標文件鏈接,從而創建可執行目標文件、共享庫文件或者其他可重定位目標文件。ELF可重定位目標文件有ELF頭、節頭表以及夾在ELF頭和節頭表之間的各個不同的節組成。

在命令行中使用readelf -a -W hello.o >hello.elf命令,可以列出hello.o各節的基本信息,並保存在hello.elf文件中,下面是hello.elf文件的全文:

ELF Header:

  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 

  Class:                             ELF64

  Data:                              2's complement, little endian

  Version:                           1 (current)

  OS/ABI:                            UNIX - System V

  ABI Version:                       0

  Type:                              REL (Relocatable file)

  Machine:                           Advanced Micro Devices X86-64

  Version:                           0x1

  Entry point address:               0x0

  Start of program headers:          0 (bytes into file)

  Start of section headers:          1216 (bytes into file)

  Flags:                             0x0

  Size of this header:               64 (bytes)

  Size of program headers:           0 (bytes)

  Number of program headers:         0

  Size of section headers:           64 (bytes)

  Number of section headers:         14

  Section header string table index: 13

 

Section Headers:

  [Nr] Name

       Type            Address          Off    Size   ES   Lk Inf Al

       Flags

  [ 0

       NULL            0000000000000000 000000 000000 00   0   0  0

       [0000000000000000]: 

  [ 1] .text

       PROGBITS        0000000000000000 000040 00007f 00   0   0  1

       [0000000000000006]: ALLOC, EXEC

  [ 2] .rela.text

       RELA            0000000000000000 000358 0000d8 18  11   1  8

       [0000000000000040]: INFO LINK

  [ 3] .data

       PROGBITS        0000000000000000 0000bf 000000 00   0   0  1

       [0000000000000003]: WRITE, ALLOC

  [ 4] .bss

       NOBITS          0000000000000000 0000bf 000000 00   0   0  1

       [0000000000000003]: WRITE, ALLOC

  [ 5] .rodata.str1.8

       PROGBITS        0000000000000000 0000c0 000026 01   0   0  8

       [0000000000000032]: ALLOC, MERGE, STRINGS

  [ 6] .rodata.str1.1

       PROGBITS        0000000000000000 0000e6 00000d 01   0   0  1

       [0000000000000032]: ALLOC, MERGE, STRINGS

  [ 7] .comment

       PROGBITS        0000000000000000 0000f3 00002c 01   0   0  1

       [0000000000000030]: MERGE, STRINGS

  [ 8] .note.GNU-stack

       PROGBITS        0000000000000000 00011f 000000 00   0   0  1

       [0000000000000000]: 

  [ 9] .eh_frame

       PROGBITS        0000000000000000 000120 000040 00   0   0  8

       [0000000000000002]: ALLOC

  [10] .rela.eh_frame

       RELA            0000000000000000 000430 000018 18  11   9  8

       [0000000000000040]: INFO LINK

  [11] .symtab

       SYMTAB          0000000000000000 000160 0001b0 18  12  10  8

       [0000000000000000]: 

  [12] .strtab

       STRTAB          0000000000000000 000310 000041 00   0   0  1

       [0000000000000000]: 

  [13] .shstrtab

       STRTAB          0000000000000000 000448 000077 00   0   0  1

       [0000000000000000]: 

 

There are no section groups in this file.

 

There are no program headers in this file.

 

There is no dynamic section in this file.

 

Relocation section '.rela.text' at offset 0x358 contains 9 entries:

    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend

0000000000000016  000000050000000a R_X86_64_32            0000000000000000 .rodata.str1.8 + 0

000000000000001b  0000000b00000002 R_X86_64_PC32          0000000000000000 puts - 4

0000000000000025  0000000c00000002 R_X86_64_PC32          0000000000000000 exit - 4

0000000000000032  000000060000000a R_X86_64_32            0000000000000000 .rodata.str1.1 + 0

0000000000000041  0000000d00000002 R_X86_64_PC32          0000000000000000 __printf_chk - 4

0000000000000054  0000000e00000002 R_X86_64_PC32          0000000000000000 strtol - 4

000000000000005b  0000000f00000002 R_X86_64_PC32          0000000000000000 sleep - 4

000000000000006a  0000001000000002 R_X86_64_PC32          0000000000000000 stdin - 4

000000000000006f  0000001100000002 R_X86_64_PC32          0000000000000000 _IO_getc - 4

 

Relocation section '.rela.eh_frame' at offset 0x430 contains 1 entry:

    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend

0000000000000020  0000000200000002 R_X86_64_PC32          0000000000000000 .text + 0

 

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

 

Symbol table '.symtab' contains 18 entries:

   Num:    Value          Size Type    Bind   Vis      Ndx Name

     00000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 

     10000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c

     20000000000000000     0 SECTION LOCAL  DEFAULT    1 

     30000000000000000     0 SECTION LOCAL  DEFAULT    3 

     40000000000000000     0 SECTION LOCAL  DEFAULT    4 

     50000000000000000     0 SECTION LOCAL  DEFAULT    5 

     60000000000000000     0 SECTION LOCAL  DEFAULT    6 

     70000000000000000     0 SECTION LOCAL  DEFAULT    8 

     80000000000000000     0 SECTION LOCAL  DEFAULT    9 

     90000000000000000     0 SECTION LOCAL  DEFAULT    7 

    100000000000000000   127 FUNC    GLOBAL DEFAULT    1 main

    110000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts

    120000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND exit

    130000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __printf_chk

    140000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND strtol

    150000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND sleep

    160000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND stdin

    170000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _IO_getc

 

No version information found in this file.

 

下面挑選幾個重要部分進行解釋

(1) ELF Header

ELF Header:

  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 

  Class:                             ELF64

  Data:                              2's complement, little endian

  Version:                           1 (current)

  OS/ABI:                            UNIX - System V

  ABI Version:                       0

  Type:                              REL (Relocatable file)

  Machine:                           Advanced Micro Devices X86-64

  Version:                           0x1

  Entry point address:               0x0

  Start of program headers:          0 (bytes into file)

  Start of section headers:          1216 (bytes into file)

  Flags:                             0x0

  Size of this header:               64 (bytes)

  Size of program headers:           0 (bytes)

  Number of program headers:         0

  Size of section headers:           64 (bytes)

  Number of section headers:         14

  Section header string table index: 13

 

ELF Header即ELF頭,其中指明瞭一些基本信息。如class項指明瞭這個文件是ELF64格式的,Data項指明數據以二進制補碼形式表示、小端存儲,machine項指明瞭這個程序適配於x86-64機器,type項指明這個文件是可重定位文件,Start of section headers指明瞭節頭表的開始位置離文件位置的偏移量是1216個字節,size of this header和size of section header分別指明瞭這個ELF頭和節頭表中一個節頭項的大小均爲64字節,number of section headers指明瞭節頭表共有14個節頭,section header string table index指明瞭字符串表在節頭中的索引是13。

 

(2) Section Headers

Section Headers:

  [Nr] Name

       Type            Address          Off    Size   ES   Lk Inf Al

       Flags

  [ 0

       NULL            0000000000000000 000000 000000 00   0   0  0

       [0000000000000000]: 

  [ 1] .text

       PROGBITS        0000000000000000 000040 00007f 00   0   0  1

       [0000000000000006]: ALLOC, EXEC

  [ 2] .rela.text

       RELA            0000000000000000 000358 0000d8 18  11   1  8

       [0000000000000040]: INFO LINK

  [ 3] .data

       PROGBITS        0000000000000000 0000bf 000000 00   0   0  1

       [0000000000000003]: WRITE, ALLOC

  [ 4] .bss

       NOBITS          0000000000000000 0000bf 000000 00   0   0  1

       [0000000000000003]: WRITE, ALLOC

  [ 5] .rodata.str1.8

       PROGBITS        0000000000000000 0000c0 000026 01   0   0  8

       [0000000000000032]: ALLOC, MERGE, STRINGS

  [ 6] .rodata.str1.1

       PROGBITS        0000000000000000 0000e6 00000d 01   0   0  1

       [0000000000000032]: ALLOC, MERGE, STRINGS

  [ 7] .comment

       PROGBITS        0000000000000000 0000f3 00002c 01   0   0  1

       [0000000000000030]: MERGE, STRINGS

  [ 8] .note.GNU-stack

       PROGBITS        0000000000000000 00011f 000000 00   0   0  1

       [0000000000000000]: 

  [ 9] .eh_frame

       PROGBITS        0000000000000000 000120 000040 00   0   0  8

       [0000000000000002]: ALLOC

  [10] .rela.eh_frame

       RELA            0000000000000000 000430 000018 18  11   9  8

       [0000000000000040]: INFO LINK

  [11] .symtab

       SYMTAB          0000000000000000 000160 0001b0 18  12  10  8

       [0000000000000000]: 

  [12] .strtab

       STRTAB          0000000000000000 000310 000041 00   0   0  1

       [0000000000000000]: 

  [13] .shstrtab

       STRTAB          0000000000000000 000448 000077 00   0   0  1

       [0000000000000000]: 

 

Section Headers即爲節頭表,指明瞭各個節頭的基本信息。如type指明瞭此節的類型,address指明瞭此節的地址,size指明瞭此節的大小

 

(3).rela.text

這是一個節,包含了關於text節的重定位信息

Relocation section '.rela.text' at offset 0x358 contains 9 entries:

    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend

0000000000000016  000000050000000a R_X86_64_32            0000000000000000 .rodata.str1.8 + 0

000000000000001b  0000000b00000002 R_X86_64_PC32          0000000000000000 puts - 4

0000000000000025  0000000c00000002 R_X86_64_PC32          0000000000000000 exit - 4

0000000000000032  000000060000000a R_X86_64_32            0000000000000000 .rodata.str1.1 + 0

0000000000000041  0000000d00000002 R_X86_64_PC32          0000000000000000 __printf_chk - 4

0000000000000054  0000000e00000002 R_X86_64_PC32          0000000000000000 strtol - 4

000000000000005b  0000000f00000002 R_X86_64_PC32          0000000000000000 sleep - 4

000000000000006a  0000001000000002 R_X86_64_PC32          0000000000000000 stdin - 4

000000000000006f  0000001100000002 R_X86_64_PC32          0000000000000000 _IO_getc - 4

 

其中,Offset指明瞭需要重定位的位置相對於所在節起始位置的字節偏移量,若蟲定位的是變量的位置,那麼所在節是.data節;若重定位的是函數的位置,則所在節是.text節。Info項指出了當前需要重定位的符號所引用的符號在符號表中的索引值以及相應的重定位類型。其中info的高32位是符號的索引,低32位是重定位的類型。Type項其實就是info項低32位表示的內容,即重定位的類型。其中,R_X86_64_32指明引用處採用絕對地址的尋址方式,即有效地址就是重定位後的64位地址;R_X86_64_PC32指明引用處採用相對尋址的方式,即有效地址爲PC的內容加上重定位後的64位地址,PC的內容是下條指令的地址。可以看到,函數符號的尋址全都採用相對尋址,剩下的兩個字符串常量都是絕對尋址。

 

(4).symtab

此節是符號表

Symbol table '.symtab' contains 18 entries:

   Num:    Value          Size Type    Bind   Vis      Ndx Name

     00000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 

     10000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c

     20000000000000000     0 SECTION LOCAL  DEFAULT    1 

     30000000000000000     0 SECTION LOCAL  DEFAULT    3 

     40000000000000000     0 SECTION LOCAL  DEFAULT    4 

     50000000000000000     0 SECTION LOCAL  DEFAULT    5 

     60000000000000000     0 SECTION LOCAL  DEFAULT    6 

     70000000000000000     0 SECTION LOCAL  DEFAULT    8 

     80000000000000000     0 SECTION LOCAL  DEFAULT    9 

     90000000000000000     0 SECTION LOCAL  DEFAULT    7 

    100000000000000000   127 FUNC    GLOBAL DEFAULT    1 main

    110000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts

    120000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND exit

    130000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __printf_chk

    140000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND strtol

    150000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND sleep

    160000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND stdin

    170000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _IO_getc

 

如上圖,符號表包含了在程序模塊中被定義和引用的所有符號的相關信息。其中,num是符號表索引,value是符號位置相對於所在節位置的偏移量,size是符號所表示對象的大小,type是符號的類型,bind是符號的綁定屬性,ndx是符號所在節在節頭表中的索引,name就是符號的名稱。

Type這一項中,NOTYPE代表未定義類型,FILE代表文件,SECTION代表節,FUNC代表函數。Bind這一項中,LOCAL和GLOBAL分別代表本地符號(局部符號)和全局符號,另外,還有WEAK代表弱符號。

NDX用於指出符號所在節在節頭表中的索引,其中有些符號屬於三種特殊僞節之一,僞節在節頭表中沒有相應的表項,無法表示其索引值,因而用以下特殊的索引值表示:ABS表示該符號不會由於重定位而發生值的改變,即不該被重定位;UND表示未定義符號,即在本模塊引用而在其他模塊定義的符號;COM表示還未被分配位置的未初始化的變量。

4.4 Hello.o的結果解析

以下格式自行編排,編輯時刪除

使用命令objdump -d -r hello.o>hello.o.s可以將hello.o中的代碼段反彙編成彙編語言代碼,並通過Linux管道存儲在hello.o.s文件中。下面是hello.o.s的全部內容:

 

hello.o:     file format elf64-x86-64

 

Disassembly of section .text:

 

0000000000000000 <main>:

   055                      push   %rbp

   153                      push   %rbx

   248 83 ec 08             sub    $0x8,%rsp

   683 ff 04                cmp    $0x4,%edi

   975 0a                   jne    15 <main+0x15>

   b: 48 89 f5                mov    %rsi,%rbp

   e: bb 00 00 00 00          mov    $0x0,%ebx

  13: eb 4d                   jmp    62 <main+0x62>

  15: bf 00 00 00 00          mov    $0x0,%edi

         16: R_X86_64_32   .rodata.str1.8

  1a: e8 00 00 00 00          callq  1f <main+0x1f>

         1b: R_X86_64_PC32 puts-0x4

  1f: bf 01 00 00 00          mov    $0x1,%edi

  24: e8 00 00 00 00          callq  29 <main+0x29>

         25: R_X86_64_PC32 exit-0x4

  2948 8b 4d 10             mov    0x10(%rbp),%rcx

  2d48 8b 55 08             mov    0x8(%rbp),%rdx

  31: be 00 00 00 00          mov    $0x0,%esi

         32: R_X86_64_32   .rodata.str1.1

  36: bf 01 00 00 00          mov    $0x1,%edi

  3b: b8 00 00 00 00          mov    $0x0,%eax

  40: e8 00 00 00 00          callq  45 <main+0x45>

         41: R_X86_64_PC32 __printf_chk-0x4

  4548 8b 7d 18             mov    0x18(%rbp),%rdi

  49: ba 0a 00 00 00          mov    $0xa,%edx

  4e: be 00 00 00 00          mov    $0x0,%esi

  53: e8 00 00 00 00          callq  58 <main+0x58>

         54: R_X86_64_PC32 strtol-0x4

  5889 c7                   mov    %eax,%edi

  5a: e8 00 00 00 00          callq  5f <main+0x5f>

         5b: R_X86_64_PC32 sleep-0x4

  5f83 c3 01                add    $0x1,%ebx

  6283 fb 07                cmp    $0x7,%ebx

  657e c2                   jle    29 <main+0x29>

  6748 8b 3d 00 00 00 00    mov    0x0(%rip),%rdi        # 6e <main+0x6e>

         6a: R_X86_64_PC32 stdin-0x4

  6e: e8 00 00 00 00          callq  73 <main+0x73>

         6f: R_X86_64_PC32 _IO_getc-0x4

  73: b8 00 00 00 00          mov    $0x0,%eax

  7848 83 c4 08             add    $0x8,%rsp

  7c5b                      pop    %rbx

  7d5d                      pop    %rbp

  7e: c3                      retq   

 

機器語言與彙編語言類似,也是由一條條指令構成的,每條指令由一串二進制字符串構成,通常以16進製表示在程序員面前。指令的長度不是固定的,由操作碼和操作數構成。彙編語言和機器語言存在着一一對應的關係,也即,彙編語言就是機器語言按照一定規則的文本級表示。

針對編譯生成的彙編代碼和彙編生成的機器語言,以及反彙編生成的彙編代碼,存在以下不同:

首先,立即數的書寫不同。在彙編代碼中,立即數可以用10進制書寫,但在機器語言中,統統是16進制;彙編代碼中是從左往右按照自然順序書寫,機器代碼中取決於指定的存儲方式,本例中是小端存儲,則低位字節在左,高位字節在右。

其次,對字符串常量的引用不同。在編譯生成的彙編代碼中,引用字符串常量是直接傳送首地址,而在機器代碼中,則是將本該填寫字符串常量的位置全部置零,並在這些0的起始地址添加一條重定位條目,指明需要重定位的位置、重定位的尋址方式以及該符號所在的節和名稱。

再次,分支結構轉移的實現細節不同。在編譯產生的彙編代碼中,各個分支都有自己的標識,如.L3等,但在反彙編產生的彙編代碼中,則是直接用相對於main函數首地址的偏移量代表各分支的首地址。

最後,函數調用的實現上存在差異。在編譯生成的彙編代碼中,call指令後面緊跟的是函數的標識符;而在機器代碼中,標識符的位置全部置零,並在其後增加一個重定位條目,指明需要重定位的位置、重定位的尋址方式以及被重定位的符號。這裏需要指出,在hello.o反彙編生成的代碼中,需要重定位的一種是字符串常量,另一種是函數;前者採用的尋址方式都是絕對尋址,後者採用的尋址方式都是相對尋址。採用相對尋址時,需要使用PC的值加上偏移地址,這裏的偏移地址就是重定位後原來被置零的地方應該填寫的值,即重定位值。而這裏使用的PC應是本條call指令所在的地址,然而PC會自動增加,指向下一條指令,因此我們需要先把PC的值減4 。這也就是爲什麼,重定位條目中函數的標識符後都會再加一個-0x4 。

 

4.5 本章小結

本章我們探討了彙編的概念和作用。我們首先指明,彙編是將編譯生成的彙編語言代碼轉換爲機器語言代碼、生成可重定位目標文件的過程。然後,我們通過gcc工具嘗試了這個過程。接着,我們介紹並分析了hello的ELF格式。爲了加深對ELF文件的瞭解,我們重點講解了ELF頭、節頭表、符號表和其他一些和重定位有關的表。最後,我們使用反彙編工具objdump從機器代碼反彙編生成了新的彙編代碼並將它和機器代碼與我們通過編譯生成的彙編代碼作了細緻的比較,分析了其中的差異。通過以上的步驟,我們對彙編語言、機器語言、ELF格式,以及彙編和反彙編工具的使用有了更加深入的理解。

(第41分)

 

第5章 鏈接

5.1 鏈接的概念與作用

一個大的程序往往分成多個源文件來編寫,因而需要對各個不同源文件分別進行編譯或者彙編,而這樣會生成多個不同的目標代碼文件。此外,程序還可能調用了一些標準庫函數。鏈接,就是將所有用到了目標代碼文件,包括用到的標準庫函數目標文件,關聯到一起的過程。

注意:這兒的鏈接是指從 hello.o 到hello生成過程。

5.2 Ubuntu下鏈接的命令

 

使用ld的鏈接命令,應截圖,展示彙編過程! 注意不只連接hello.o文件

5.3 可執行目標文件hello的格式

    分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。

5.4 hello的虛擬地址空間

    使用edb加載hello,查看本進程的虛擬地址空間各段信息,並與5.3對照分析說明。   

5.5 鏈接的重定位過程分析

以下格式自行編排,編輯時刪除

objdump -d -r hello 分析hello與hello.o的不同,說明鏈接的過程。

結合hello.o的重定位項目,分析hello中對其怎麼重定位的。

5.6 hello的執行流程

以下格式自行編排,編輯時刪除

使用edb執行hello,說明從加載hello到_start,到call main,以及程序終止的所有過程。請列出其調用與跳轉的各個子程序名或程序地址。

5.7 Hello的動態鏈接分析

   (以下格式自行編排,編輯時刪除

分析hello程序的動態鏈接項目,通過edb調試,分析在dl_init前後,這些項目的內容變化。要截圖標識說明。

5.8 本章小結

 

以下格式自行編排,編輯時刪除

(第51分)

 

 

第6章 hello進程管理

6.1 進程的概念與作用

進程就是程序的一次運行過程。更確切地說,進程是一個具有一定獨立功能地程序關於某個數據集合地一次運行活動,具有着動態地含義。每進程是操作系統對處理器中程序運行過程的一個抽象,具有自己的生命週期。

進程的引入實現了每個程序獨佔計算資源和存儲資源的假象,簡化了編程、編譯、鏈接、共享和加載等整個過程。

6.2 簡述殼Shell-bash的作用與處理流程

殼是相對於OS內核而言的,它是對計算機系統的一個包裝和抽象,爲計算機系統和用戶提供了一個交互界面,可以用來幫助用戶執行各種命令。

linux環境中,程序員開啓Bash,執行一條命令,Bash就會判斷這條命令是內置命令還是外部可執行文件,判斷完畢後OS的進程管理程序就會在Bashfork一個子進程,通過設置進程組id的方式使這個子進程與Bash進程分離,然後調用execve函數執行內置命令或命令中第一個字符串代表的可執行目標文件。

 

6.3 Hellofork進程創建過程

在我們在命令行中輸入./hello並按下回車後,bash會首先解析命令行,判斷出它的工作方式是前臺還是後臺,以及它是否是內置命令。顯然hello屬於外部的可執行文件,因此,bash就會屏蔽所有的信號,然後利用fork函數創建一個子進程,在調用後通過判斷函數的返回值來判斷子進程是否創建成功,以及哪一個是父進程的返回,哪一個是子進程的返回,子進程的pid號是多少。創建成功後,解除信號阻塞。同時,bash還會將子進程放入新進程組,以免用戶輸入的中斷指令影響到整個bash進程。此時,子進程獲得與父進程完全相同的虛擬存儲空間的一個備份。

6.4 Helloexecve過程

在創建子進程並解除阻塞後,通過判斷pid的值得到子進程,利用分支結構讓子進程執行execve函數,調用可執行目標文件hello。在函數execve中,通過啓動加載器執行加載任務,將可執行目標文件hello中的.text、.data、.bss節等內同加載到當前進程的虛擬空間(通過修改當前進程上下文中關於存儲映像的一些數據結構實現,並未將hello的代碼從磁盤讀入主存)。當加載器執行完加載任務後,便轉到hello程序的第一條指令開始執行。

6.5 Hello的進程執行

以下格式自行編排,編輯時刪除

結合進程上下文信息、進程時間片,闡述進程調度的過程,用戶態與核心態轉換等等。

6.6 hello的異常與信號處理

Hello的執行過程中會出現故障、陷阱、中斷、終止這四類異常。

故障由錯誤情況引起,能夠被故障處理程序修正。若處理程序能夠修正這個錯誤情況,它就將控制返回到引起故障的指令,從而重新執行它,負責處理程序返回到內核的abort例程,abort例程會終止引起故障的應用程序。

陷阱是有意的異常,是執行一條指令的結果,如syscall,陷阱處理程序將控制返回到下一條指令。

中斷是異步發生的,是來自處理器外部的I/O設備的信號的結果。中斷髮生時,控制轉移給中斷處理程序,處理程序返回時,它就將控制返回到下一條指令,程序繼續執行。

終止是不可恢復的致命錯誤造成的結果,通常是一些硬件錯誤。終止處理程序要麼重新執行當前指令,要麼將控制返回給一個abort例程,abort例程會終止這個應用程序。

 

Hello執行過程中可能會產生很多信號,包括SIGINT SIGSTOP SIGCHILD等,它們會由相應的信號處理程序來處理。

 

下面展示Ctrl-Z後的現象:

 

從上圖可以發現,亂按對程序沒有影響,執行ctrl-z後程序停止,這時程序接收到了SIGSTOP信號,停止運行並且進入後臺,ps命令和jobs命令都可以看到它。

執行pstree後在terminal的子進程中看到了它。

上面是利用fg命令將其調入前臺,則程序繼續執行。再次掛起後使用kill命令向其發送終止信號,發現第一次調用ps命令能夠看到被殺死的進程,第二次就沒有了,jobs命令執行後也沒有看到該進程。

 

接下來我們看一看crtl-c的效果:

發現該進程已經完完全全地消失了。

6.7本章小結

本章我們主要討論了關於進程的內容,包括進程的創建和管理,以及異常的分類和信號的處理等。

(第61分)

 

第7章 hello的存儲管理

7.1 hello的存儲器地址空間

 

結合hello說明邏輯地址、線性地址、虛擬地址、物理地址的概念。

7.2 Intel邏輯地址到線性地址的變換-段式管理

Hello在運行時,OS會給進程分配一個虛擬的內存空間,而邏輯地址就是通常所說的虛擬地址。邏輯地址由段選擇符和段內偏移量組成。MMU首先根據段選擇符確定描述符表,並從描述符表中找到對應的段描述符。從中去除基地址,與邏輯地址中的段內偏移量相加,就得到了線性地址

7.3 Hello的線性地址到物理地址的變換-頁式管理

這步轉換採用多級頁表的形式,下面以2級頁表爲例。首先根據頁目錄表首地址找到頁目錄表,根據頁目錄索引找到對應的頁表,再根據線性地址中間的頁表索引找到頁表中的頁表項。最後,將頁表項中的基地址和線性地址的頁內偏移量相組合,就得到了物理地址。

7.4 TLB與四級頁表支持下的VAPA的變換

MMU對TLB查表時,首先由組索引確定TLB的組,再比較標記爲。若相等且有效位爲1,則命中,直接通過TLB進行地址轉換。否則TLB缺失,將虛擬頁號分成四級,分別在四級頁表中進行嵌套查詢,將最終得到的頁表項的基地址和線性地址內的頁內偏移量相組合,就得到了物理地址。

 

7.5 三級Cache支持下的物理內存訪問

以下格式自行編排,編輯時刪除

7.6 hello進程fork時的內存映射

以下格式自行編排,編輯時刪除

7.7 hello進程execve時的內存映射

以下格式自行編排,編輯時刪除

7.8 缺頁故障與缺頁中斷處理

以下格式自行編排,編輯時刪除

7.9動態存儲分配管理

以下格式自行編排,編輯時刪除

Printf會調用malloc,請簡述動態內存管理的基本方法與策略。

7.10本章小結

以下格式自行編排,編輯時刪除

(第7 2分)

 

第8章 hello的IO管理

8.1 LinuxIO設備管理方法

以下格式自行編排,編輯時刪除

設備的模型化:文件

設備管理:unix io接口

8.2 簡述Unix IO接口及其函數

以下格式自行編排,編輯時刪除

8.3 printf的實現分析

以下格式自行編排,編輯時刪除

https://www.cnblogs.com/pianist/p/3315801.html

從vsprintf生成顯示信息,到write系統函數,到陷阱-系統調用 int 0x80或syscall.

字符顯示驅動子程序:從ASCII到字模庫到顯示vram(存儲每一個點的RGB顏色信息)。

顯示芯片按照刷新頻率逐行讀取vram,並通過信號線向液晶顯示器傳輸每一個點(RGB分量)。

8.4 getchar的實現分析

以下格式自行編排,編輯時刪除

異步異常-鍵盤中斷的處理:鍵盤中斷處理子程序。接受按鍵掃描碼轉成ascii碼,保存到系統的鍵盤緩衝區。

getchar等調用read系統函數,通過系統調用讀取按鍵ascii碼,直到接受到回車鍵才返回。

8.5本章小結

以下格式自行編排,編輯時刪除

(第81分)

用計算機系統的語言,逐條總結hello所經歷的過程。

你對計算機系統的設計與實現的深切感悟,你的創新理念,如新的設計與實現方法。

(結論0分,缺失 -1分,根據內容酌情加分)

 

列出所有的中間產物的文件名,並予以說明起作用。

(附件0分,缺失 -1分)

 

爲完成本次大作業你翻閱的書籍與網站等

[1]  袁春風. 計算機系統基礎[M]. 北京:機械工業出版社.

[2]  .深入理解計算機系統[M]

(參考文獻0分,缺失 -1分)

 

 

 

發佈了5 篇原創文章 · 獲贊 2 · 訪問量 531
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章