哈工大计统实验
計算機系統
大作業
題 ????目 ?程序人生-Hello’s P2P???
專?????? 業 ??????計算學部??????????
學 ?? 號 ???????120L020815???????
班 ?? 級 ?????????2036011????????
學?????? 生 ???????趙美含????????? ??
指 導 教 師 ??????????劉松波?????????
計算機科學與技術學院
2021年5月
摘? 要
本文從簡單的hello.c程序入手,介紹了該程序經過預處理,編譯,匯編,鏈接后生成可執行文件的過程。同時本文還介紹了linux下的內存管理、進程管理、虛擬內存、異常信號的相關內容,通過本篇文章,對本學習的知識進行了總結。
關鍵詞:hello.c;預處理;編譯;鏈接;進程;存儲;???????????????????????????
(摘要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.c,當我們想要運行hello.c文件時,hello.c文件得首先經過預處理,編譯,匯編,鏈接4個階段從hello.c文本文件轉變為可執行文件,這樣我們的機器才能運行這個文件。
以linux系統為例,當我們在終端運行可執行文件時,shell解析這段命令,使用fork為我們的hello創建子進程,至此完成了從program到progress的過程。
當程序完成p2p過程之后,就進入了020過程
在此過程中, shell 為我們的程序調用 execve函數,execve函數啟動加載器為該進程分配獨立的虛擬內存空間,程序運行在物理內存中,CPU 為其分配時間片執行指令,調用系統I/O,printf函數顯示相應的功能。當程序運行結束后,shell 父進程負責回收 hello 進程。
至此,020過程也告一段落。
1.2 環境與工具
1.2.1 硬件環境
?
圖1 硬件環境
1.2.2 軟件環境
Windows:??? windows10、Visual studio 2022、VMware Workstation Pro、code blocks
Ubuntu:?????? Ubuntu20.04.3(64位)、code blocks
1.2.3 開發工具
Visual studio 2022
Code Blocks
1.3 中間結果
Hello.c hello.i hello.o hello.s
1.4 本章小結
本章為本篇論文的一個概述,簡單介紹了p2p過程和020過程,介紹了編寫此論文使用的軟硬件環境和開發調試工具以及編寫論文過程中的中間結果。
(第1章0.5分)
第2章 預處理
2.1 預處理的概念與作用
概念:預處理一般是指在程序源代碼被翻譯為目標代碼的過程中,生成二進制代碼之前的過程。預處理器(cpp)根據以#開頭的命令,修改顯示的C程序。
作用:
1)將源文件中用#include形式聲明的文件復制到新的程序中。比如hello.c第6-8行中的#include<stdio.h> 等命令告訴預處理器讀取系統頭文件stdio.h unistd.h stdlib.h 的內容,并把它直接插入到程序文本中。
2)用實際值替換用#define定義的字符串
3)根據#if后面的條件決定需要編譯的代碼
4)還包括此次hello中沒有的#line,#error,#pragma,以及單獨的空指令的處理。
2.2在Ubuntu下預處理的命令
預處理指令:gcc -E hello.c -o hello.i
如下圖所示:
得到hello.i文件:
2.3 Hello的預處理結果解析
·針對如下三條語句的預處理
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
2.4 本章小結
本章介紹了預處理的概念和作用,以及預處理的命令和結果解析。預處理器cpp將一個hello.c源程序編譯為hello.i,原理是根據以字符#開頭的命令,修改原始的C程序。
(第2章0.5分)
第3章 編譯
3.1 編譯的概念與作用
概念:編譯階段是編譯器ccl將文本文件hello.i翻譯成hello.s,它包含一個匯編語言程序,該程序包含一個main的定義
作用:把高級語言翻譯成機器可以“聽懂”的機器語言,連接高級語言和機器語言的橋梁。
3.2 在Ubuntu下編譯的命令
指令:gcc -S hello.i -o hello.s,下圖為編譯展示:
編譯結果:
3.3 Hello的編譯結果解析
3.3.1開頭匯編指令:
.file——C文件聲明
.text——代碼段
.section .radata——只讀數據段
.align 8——聲明對指令或者數據的存放地址進行對齊的方式
.string——聲明string型數據
3.3.2.cfi指令
Call Frame infromation的意思,.cfi_startproc 用在每個函數的開始,用于初始化一些內部數據結構,.cfi_endproc 在函數結束的時候使用與.cfi_startproc相配套使用。
3.3.3 常量
即字符串常量
保存在如下數據段中
3.3.4變量
局部變量為for循環中的i,由于i最初被賦值為0,所以找到賦值0操作的,即為i,為第42行。
由上圖還可以看到第一個參數被復制到-20(%rbp)棧中
該程序包含argv[]數組的三個元素:
數組中的元素一般保存在連續地址中,尋址方式即可找到數組:
3.3.5賦值操作
本代碼中復制操作是在進行for循壞過程中,對局部變量i進行的賦值操作,把0賦值給i:
3.3.6算數操作
也就是for循環中每次的i++,見下圖51行,每次都加一,每次都在L3中判斷for循環中的條件,滿足則跳到L4,執行一系列指令后將i+1。
3.3.7判斷操作
3.3.8控制轉移
在判斷之后會有條件控制,不同的CC會跳轉到不同的指令,控制轉移分別分為if控制轉移和for循環的控制轉移。
相等的話跳轉到L2,L2賦值之后跳轉到L3,不相等的話繼續執行,打印語句。
L2轉移到L3,L3是一個for循環,每次都會比較i和7的大小,如果小于等于就會跳轉到L4執行for循環中的指令,不相等則退出for循環。
3.3.9數組指針操作
數組元素有字符串數組argv[],指針有指向數組argv的指針。
對于數組元素的操作,通常是將數組首個元素的地址放入棧中,而在該程序中也是這樣,將數組argv首元素,也是指向argv的指針的地址放入了-32(%rbp)中。
在for循環體中,用起始地址加上偏移量字節大小來訪問的,采用這種尋址方式,就能訪問到數組中的每個元素,如下圖所示:
3.3.10函數操作
函數調用使用call指令
函數返回使用ret指令
3.4 本章小結
本章主要介紹匯編過程,使用指令gcc -S hello.i -o hello.s,把hello.i轉為hello.s,即把hello.s翻譯成機器能聽懂的匯編語言,是高級語言和機器語言之間的橋梁,本章介紹了匯編語言的各種指令,如call ret move 判斷等指令,使學生掌握了看懂匯編語言的能力。
(第3章2分)
第4章 匯編
4.1 匯編的概念與作用
匯編概念:匯編階段是指匯編器(as)將hello.s翻譯成機器語言指令,把這些指令打包成一種叫做可重定位目標程序的格式,并且保存在hello.o中。
匯編作用:將匯編語言翻譯為機器語言,并將相關指令以可重定位目標程序格式保存在.o文件中
4.2 在Ubuntu下匯編的命令
命令:as hello.s -o hello.o
4.3 可重定位目標elf格式
ELF頭以一個16字節的序列開始,這個序列描述了生成該文件系統下的字的大小以及一些其他信息。ELF頭剩下的部分包含幫助鏈接器語法分析和解釋目標文件的信息:包括ELF頭的大小、目標文件的類型、機器類型、節頭部表的文件偏移,以及節頭部表中條目的大小和數量。具體ELF頭的代碼如下:
描述了.o文件中每一個節出現的位置,大小,目標文件中的每一個節都有一個固定大小的條目。具體內容如下圖所示:
重定位是將EFL文件中的未定義符號關聯到有效值的處理過程。在hello.o中,對printf,exit等函數的未定義的引用和全局變量(sleepsecs)替換為該進程的虛擬地址空間中機器代碼所在的地址。
符號表(.symtab)是用來存放程序中定義和引用的函數和全局變量的信息。重定位需要引用的符號都在其中聲明。具體信息如下所示:
4.4 Hello.o的結果解析
通過objdump -d -r hello.o? 生成hello.o的反匯編,下面與第3章的 hello.s進行對照分析。
與hello.s對比的差別如下:
4.5 本章小結
本章介紹了hello從hello.s到hello.o的匯編過程,查看了hello.o的ELF格式,使用objdump得到反匯編代碼,還將其與hello.s進行了比較,了解到了從匯編到機器匯編的轉換。
(第4章1分)
第5章 鏈接
5.1 鏈接的概念與作用
鏈接概念:連接的概念是指連接器(ld)將存有printf等函數的預編譯好的目標文件合并到hello.o程序的過程。如在hello函數中調用了printf函數,它是每個編譯器都提供的標準C庫中的一個函數,printf函數存在于一個預編譯好的目標文件中,而這個文件要通過ld合并到我們的hello.o文件中。
鏈接的作用:將存有printf等函數的預編譯好的目標文件合并到hello.o程序。
5.2 在Ubuntu下鏈接的命令
命令:ld -o hello -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o hello.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o
生成可執行文件hello.o
5.3 可執行目標文件hello的格式
ELF Header格式如下:
類型為EXEC表示為可執行文件。
Section Headers格式如下:
Section Headers:節頭部表,記錄各節名稱、類型、地址、偏移量、大小、全體大小、旗標、鏈接、信息、對齊。根據Section Headers中的信息我們就可以用HexEdit定位各個節所占的區間(起始位置,大小)。
Symbol table的信息如下:
5.4 hello的虛擬地址空間
使用edb加載hello,結果如下:
虛擬地址信息如下:
5.5 鏈接的重定位過程分析
鏈接加入了新的函數,如printf,getchar,sleep 等函數。
增加了.init和.plt節
hello.o中標注了重定位信息的部分均被具體的地址,數據所代替
5.6 hello的執行流程
使用edb執行hello,下表展示從加載hello到_start,到call main,以及程序終止的所有過程并列出其調用與跳轉的各個子程序名或程序地址。
5.7 Hello的動態鏈接分析
在進行動態鏈接前,首先要進行靜態鏈接,生成部分鏈接的可執行目標文件hello。動態鏈接采用了延遲加載的策略,即在調用函數時才進行符號的映射。使用偏移量表got+過程鏈接表plt實現函數的動態鏈接。got中存放函數目標地址,為每個全局函數創建一個副本函數,并將對函數的調用轉換成對副本函數調用。
查看dl_init函數調用前后.got.plt節的變化
5.8 本章小結
鏈接是編譯hello.c程序的最后一步,我們首先了解了連接的概念和作用,然后分析了hello的ELF格式,使用edb加載hello并進行了重定位分析。
(第5章1分)
第6章 hello進程管理
6.1 進程的概念與作用
進程概念:進程是操作系統對一個正在運行的程序的一種抽象。在一個系統上可以同時運行多個進程,而每個進程都好像是單獨的使用硬件,在大多數系統中,需要運行的進程數可以多于他們的CPU個數,一個CPU像是在并發的執行多個進程,這就是處理器在進程間切換來實現的。
進程作用:想hello這樣的程序在現代系統上運行時,進程會提供一種假象,好像系統上只有這個程序在運行,程序看上去是獨占的使用處理器,主存和io設備,處理器看上去好像在不間斷地執行程序中的指令,這些假象都是通過進程中的概念來實現的。
6.2 簡述殼Shell-bash的作用與處理流程
shell是一個應用程序,他在操作系統中提供了一個用戶與系統內核進行交互的界面。它解釋由用戶輸入的命令并且把它們送到內核。
1.讀取用戶由鍵盤輸入的命令行。
2.分析命令,以命令名作為文件名,并將其它參數改造為系統調用execve( )內部處理所要求的形式。
3.終端進程調用fork( )建立一個子進程。
4.終端進程本身調用wait4()來等待子進程完成(如果是后臺命令,則不等待)。當子進程運行時調用execve(),子進程根據文件名到目錄中查找有關文件,調入內存,執行這個程序。
5.如果命令末尾有&,則終端進程不用執行系統調用wait4(),立即發提示符,讓用戶輸入下一條命令;否則終端進程會一直等待,當子進程完成工作后,向父進程報告,此時中斷進程醒來,作必要的判別工作后,終端發出命令提示符,重復上述處理過程。
6.3 Hello的fork進程創建過程
當我們在終端運行之前得到的可執行文件,使用./hello的命令,shell會對輸入的命令行進行解析,因為 hello 不是一個內置的shell 命令所以解析之后終端程序判斷./hello的語義為執行當前目錄下的可執行目標文件 hello,之后終端程序首先會調用 fork 函數創建一個新的運行的子進程。
Shell通過調用fork函數創建一個新的運行的子程序,新創建的子進程得到與父進程用戶及虛擬內存空間相同的一份副本,包括代和數據段,堆棧和共享庫。
6.4 Hello的execve過程
調用函數fork創建新的子進程之后,子進程會調用execve函數,在當前進程的上下文中加載并運行一個新程序hello。execve 函數從不返回,它將刪除該進程的代碼和地址空間內的內容并將其初始化,然后通過跳轉到程序的第一條指令或入口點來運行該程序。將私有的區域映射進來,然后將公共的區域映射進來。后面加載器跳轉到程序的入口點,即設置PC指向_start 地址。_start函數最終調用hello中的 main 函數,這樣,就完成成了在子進程中的加載。
6.5 Hello的進程執行
結合進程上下文信息、進程時間片,闡述進程調度的過程,用戶態與核心態轉換等等。
處理器使用一個寄存器提供兩種模式的區分。用戶模式的進程不允許執行特殊指令,不允許直接引用地址空間中內核區的代碼和數據;內核模式進程可以執行指令集中的任何命令,并且可以訪問系統中的任何內存位置。
一個進程執行它的控制流的一部分的每一時間段叫做時間片。
對于hello的進程執行,具體過程如下:鍵盤輸入./hello zmh yeye 1
首先shell通過加載器加載可執行目標文件hello,操作系統進行上下文切換,切換到hello的進程中,此時為用戶態,執行完相應函數后,調用sleep函數,進入內核態,當sleep的時間完成后時定時器發送一個中斷信號,此時進入內核狀態執行中斷處理,將hello進程從等待隊列中移出重新加入到運行隊列,上下文切換再進入hello進程,回到用戶態。
6.6 hello的異常與信號處理
hello的異常可以分為四類:中斷,陷阱,故障和終止
1 中斷
來自I/O設備的信號 異步 總是返回到下一條指令
2 陷阱
有意的異常 同步 總是返回到下一條指令
3 故障
潛在可恢復的錯誤 同步 可能返回到當前指令
4 終止
不可恢復的錯誤 同步 不會返回
鍵盤中各種操作導致的異常
6.7本章小結
本章了解了進程的概念與作用,敘述了shell的處理流程,說明了hello的進程處理和異常信號執行。
(第6章1分)
第7章 hello的存儲管理
7.1 hello的存儲器地址空間
程序代碼經過編譯后出現在 匯編程序中地址。邏輯地址由選擇符 (在實模式下是描述符,在保護模式下是用來選擇描述符的選擇符)和偏移量(偏 移部分)組成。
也叫虛擬地址,是邏輯地址到物理地址變換之間的中間層,即連續的虛擬地址。
虛擬地址是程序保護模式下,程序訪問存儲器所使用的邏輯地址稱為虛擬地址,與實地址模式下的分段地址類似,虛擬地址也可以寫為[段:偏移量]的形式,這里的段是指段選擇器。
計算機系統的主存被組織成一個由M個連續的字節大小的單元組成的數組。每個字節都有一個唯一的物理地址。
7.2 Intel邏輯地址到線性地址的變換-段式管理
一個邏輯地址由兩部份組成,段標識符:段內偏移量。段標識符是由一個16位長的字段組成,稱為段選擇符。其中前13位是一個索引號。后面3位包含一些硬件細節。轉換過程如下所示:
7.3 Hello的線性地址到物理地址的變換-頁式管理
通過分頁機制完成,即對虛擬地址的內存空間進行分頁。在任意時刻,虛擬頁面的集合都分成三個不相交的子集
系統將每個段分割為被稱為虛擬頁(VP)的大小固定的塊來作為進行數據傳輸的單元,虛擬地址分為虛擬頁號VPN和虛擬頁偏移量VPO,根據位數限制分析可以確定VPN和VPO分別占多少位是多少。
通過頁表基址寄存器PTBR+VPN在頁表中獲得條目PTE,一條PTE中包含有效位、權限信息、物理頁號。如果有效位是0+NULL則代表沒有在虛擬內存空間中分配該內存。如果是有效位0+非NULL,則代表在虛擬內存空間中分配了但是沒有被緩存到物理內存中。如果有效位是1則代表該內存已經緩存在了物理內存中,可以得到其物理頁號PPN,與虛擬頁偏移量共同構成物理地址PA。
7.4 TLB與四級頁表支持下的VA到PA的變換
36位VPN被劃分成四個9位的片,每個篇被用作到一個頁表的偏移量。CR3寄存器包含L1頁表的物理地址。VPN1提供一個到L1 PTE的偏移量,這個PTE包含L2頁表的基地址。VPN2提供到一個L2 PTE的偏移量,以此類推。
7.5 三級Cache支持下的物理內存訪問
使用上一步得到的PA,首先取組索引對應位,向L1cache中尋找對應組。如果存在,則比較標志位,并檢查對應行的有效位是否為1。如果上述條件均滿足則命中。否則按順序對L2cache、L3cache、內存進行相同操作,直到出現命中。然后向上級cache返回直到L1cache。如果有空閑塊則將目標塊放置到空閑塊中,否則將緩存中的某個塊驅逐,將目標塊放到被驅逐塊的原位置。
7.6 hello進程fork時的內存映射
當fork函數被shell調用時,會分配給hello一個唯一的PID。為了給hello創建虛擬內存,fork創建了當前進程的mm_struct、區域結構和頁表的原樣副本。它將兩個進程中的每個頁面都標記位只讀,并將兩個進程中的每個區域結構都標記為私有的寫時復制。
當fork在hello中返回時,hello現在的虛擬內存剛好和調用shell的虛擬內存相同。當這兩個進程中的任何一個進行寫操作時,寫時復制機制會創建新頁面。因此也就為每個進程保持了私有地址空間的概念。
7.7 hello進程execve時的內存映射
Execve函數在當前進程中加載并運行包含目標文件a.out中的程序,用a.out程序有效的替換了當前的程序。加載并運行a.out需要以下幾個步驟:
之后調度此進程時,它將從這個入口點開始執行。
7.8 缺頁故障與缺頁中斷處理
當指令引用一個虛擬地址,在MMU中查找頁表時發現與該地址相對應的物理地址不在內存中,因此必須從磁盤中取出時就會發生故障。缺頁故障后會有如下處理:
7.9動態存儲分配管理
當運行時需要額外內存時,用動態內存分配器更方便,也有更好的移植性。
動態內存分配器維護著一個進程的虛擬內存區域,稱為堆。對于每個進程,內核維護一個變量brk,它指向堆的頂部。分配器將堆視為一組不同大小的塊的集合來維護。每個塊就是一個連續的虛擬內存片,要么是已分配的,要么是空閑的。已分配的塊顯式地保留為供應用程序使用。空閑塊可用來分配。空閑塊保持空閑,直到它顯式地被應用所分配。一個已分配的塊保持已分配狀態,直到它被釋放,這種釋放要么是應用程序顯式執行的,要么是內存分配器自身隱式執行的。
分配器分為兩種基本風格。兩種風格都要求應用顯示的分配塊,它們的不同之處在于有哪個實體來負責釋放已分配的塊:
malloc函數返回一個指針,指向大小至少為size字節的內存塊,這個塊可能包含在這個塊內的任何數據對象類型做對齊。
對比于顯式空閑鏈表,代表并不直接對空閑塊進行鏈接,而是將對內存空間中的所有塊組織成一個大鏈表,在塊的首尾的四個字節分別添加header和footer,負責維護當前塊的信息(大小和是否分配)。由于每個塊是對齊的,所以每個塊的地址低位總是0,可以用該位標注當前塊是否已經分配。可以利用header和footer中存放的塊大小尋找當前塊兩側的鄰接塊,方便進行空閑塊的合并操作。優點是簡單,缺點是搜索所需時間與堆中以分配塊和空閑塊的總數成線性關系。
顯式結構在空閑塊中增加了8個字節,分別保存當前空閑塊的前驅空閑塊的地址和后繼空閑塊的地址。顯式的結構比隱式結構多維護了一個鏈表,就是空閑塊的鏈表。這樣做的好處就是在malloc的時候,隱式的方法是要遍歷所有的塊,包括空閑塊了分配塊。但是顯式的結構只需要在空閑塊中維護的鏈表檢索就可以了,這樣降低了在malloc時候的復雜度。
關于空閑塊的維護方式一共有兩種,一種是后進先出的方式,另一種是按照地址的方式。按照地址維護很好理解,與隱式的結構大致相同。后進先出的方式的思想是,當一個分配塊被free之后,將這個塊放到鏈表的最開頭,這樣在malloc的時候會首先看一下最后被free的塊是否符合要求。這樣的好處是釋放一個塊的時候比較高效,直接放在頭部就可以。
7.10本章小結
本章介紹了hello的線性地址空間和物理到線性,線性到邏輯的變換,還介紹了hello進程fork,execve時的內存映射,以及缺頁故障與缺頁中斷處理和動態存儲分配管理。
(第7章 2分)
結論
Hello.c只是一個簡單的代碼文件,但是通過這個文件我們了解了一個C語言程序從被寫出到執行的一生,平時運行代碼文件只是簡單的點個運行按鈕,但是真正了解如何編譯后才發現里面內容之豐富,知識之廣泛。本文的hello.c一共經歷了一下幾種剖析:
(結論0分,缺失 -1分,根據內容酌情加分)
附件
列出所有的中間產物的文件名,并予以說明起作用。
(附件0分,缺失 -1分)
參考文獻
為完成本次大作業你翻閱的書籍與網站等
[1]? 林來興. 空間控制技術[M]. 北京:中國宇航出版社,1992:25-42.
[2]? 辛希孟. 信息技術與信息服務國際研討會論文集:A集[C]. 北京:中國科學出版社,1999.
[3]? 趙耀東. 新時代的工業工程師[M/OL]. 臺北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
[4]? 諶穎. 空間交會控制理論與方法研究[D]. 哈爾濱:哈爾濱工業大學,1992:8-13.
[5]? KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.
[6]? CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.
(參考文獻0分,缺失 -1分)
總結
- 上一篇: Android阿面试积累,讲的真透彻
- 下一篇: c语言调用延时子程序的例子,C语言精确延