C++程序的执行过程
要理解一個(gè)程序的執(zhí)行過程,首先要理解什么是編譯器。我們用C語言寫的程序,計(jì)算機(jī)只能識別機(jī)器語言(二進(jìn)制指令),計(jì)算機(jī)并不能理解。因此,必須 將C語言轉(zhuǎn)換為機(jī)器語言。編譯器就是用來實(shí)現(xiàn)這一功能的。編譯器將源代碼文件按照一定的對應(yīng)規(guī)則映射程計(jì)算機(jī)能夠識別的二進(jìn)制指令。
?
關(guān)于源文件、目標(biāo)文件和可執(zhí)行文件
源文件:保存源代碼的文件(*.c, *.cpp)
目標(biāo)文件:編譯器根據(jù)源文件創(chuàng)建的機(jī)器語言指令成為目標(biāo)代碼,包含目標(biāo)代碼的磁盤文件即目標(biāo)文件。
?一般為(*.obj)文件,Linux下為(*.o)文件。
編譯完源代碼后生成的目標(biāo)文件并不能直接執(zhí)行。一般我們編寫的程序都會(huì)引用基本的庫函數(shù),因此在運(yùn)行程序之前還要把庫函用定義好的目標(biāo)代碼替換,這個(gè)過程稱為鏈接。就是把自己寫的源代碼的目標(biāo)文件與庫函數(shù)的目標(biāo)文件組合起來,生成最終的可執(zhí)行文件。鏈接由鏈接器完成。
一般程序的執(zhí)行過程:
程序先由程序員編輯創(chuàng)建并保存在硬盤上,源程序在機(jī)器上表現(xiàn)為01組成的位序列,8個(gè)位一個(gè)字節(jié),每個(gè)字節(jié)表示一個(gè)文本字符,它是以ascii碼的形式表示的。只由ascii字符組成的文件叫做文本文件,所有其他的叫做二進(jìn)制文件。
? ? ? ?為了讓機(jī)器能夠識別并運(yùn)行程序,每條語句必須被轉(zhuǎn)為低級機(jī)器語言指令,然后將指令按照可執(zhí)行目標(biāo)程序的格式打包,并以二進(jìn)制磁盤文件的形式存放起來。以c程序?yàn)槔?#xff0c;轉(zhuǎn)換過程大致分為預(yù)處理,編譯,匯編,鏈接四個(gè)步驟。下面進(jìn)行詳細(xì)解釋。
? ? ? ?預(yù)處理器根據(jù)以字符#開頭的命令修改原始的c程序,比如#include<stdio.h>告訴預(yù)處理器讀取系統(tǒng)頭文件stdio.h的內(nèi)容,并把它直接插入程序文本中,將#define的變量替換等等,結(jié)果得到了另一個(gè)c程序,通常以.i作為文件擴(kuò)展名。
? ? ? ?編譯器將文本文件hello.i翻譯成hello.s,它包含了一個(gè)匯編語言程序。匯編語言程序中的每條語句都以一種標(biāo)準(zhǔn)的文本格式確切的描述一條低級機(jī)器語言指令。
? ? ? ?匯編器將匯編程序翻譯為機(jī)器語言指令,把這些指令打包成可重定位目標(biāo)程序(relocateble object program)的格式,并把結(jié)果保存在hello.o中。hello.o文件是二進(jìn)制文件,因?yàn)樗淖止?jié)編碼是機(jī)器語言指令而不是ascii碼。如果用文本編輯器打開hello.o會(huì)看到一堆亂碼。
? ? ? ?鏈接階段,比如hello中用到了printf函數(shù),這是標(biāo)準(zhǔn)c庫的函數(shù),存在于一個(gè)名為printf.o的單獨(dú)編譯好的目標(biāo)文件中,這個(gè)文件必須以某種方式合并到我們編譯好的的目標(biāo)文件中。鏈接器(ld)程序負(fù)責(zé)處理這種合并,結(jié)果得到hello文件,它是可執(zhí)行目標(biāo)文件,可以被加載到內(nèi)存中,由系統(tǒng)執(zhí)行。
? ? ? ?轉(zhuǎn)換完成之后就是執(zhí)行了。在unix系統(tǒng)中,shell是一個(gè)命令行解釋器,輸出一個(gè)提示符,等待用戶輸入然后執(zhí)行命令。如果輸入的第一個(gè)單詞不是一個(gè)內(nèi)置的shell命令,shell將其解釋為可執(zhí)行文件,比如輸入./hello,它將加載并運(yùn)行這個(gè)文件。hello在屏幕上輸出信息,然后終止。shell輸出一個(gè)提示符,等待下一個(gè)輸入的命令行。具體的過程為:初始時(shí),shell執(zhí)行它的指令,等待輸入。用戶輸入字符創(chuàng)“./hello”后,shell將字符逐一讀入寄存器,然后存放到存儲(chǔ)器中,敲回車鍵后,shell知道用戶結(jié)束命令輸入。然后shell執(zhí)行一系列的指令來加載可執(zhí)行的hello文件,將hello目標(biāo)文件的代碼和數(shù)據(jù)從磁盤復(fù)制到主存,數(shù)據(jù)包含輸出的字符串"HELLO,WORLD\n"。一旦目標(biāo)文件hello中的代碼和數(shù)據(jù)被加載到主存,處理器開始執(zhí)行main的機(jī)器語言指令,將字符串從主存拷貝到寄存器,并輸出到屏幕上。
? ? ? ?由于涉及大量的主存,磁盤,寄存器通信,故產(chǎn)生了cache等緩沖提高速度的設(shè)備,減少通信阻塞。
? ? ? ? 為了減少用戶的負(fù)擔(dān),操作系統(tǒng)對計(jì)算機(jī)硬件資源進(jìn)行了抽象,產(chǎn)生了進(jìn)程,線程,虛擬地址等概念。進(jìn)程是程序的一次執(zhí)行,是操作系統(tǒng)分配資源的單位,多個(gè)進(jìn)程是可以并發(fā)執(zhí)行的,并發(fā)執(zhí)行實(shí)際上每個(gè)時(shí)刻執(zhí)行的還是一個(gè)進(jìn)程,只不過進(jìn)程間切換的速度比較快,給人的感覺是并發(fā)執(zhí)行。操作系統(tǒng)為每個(gè)進(jìn)程保存執(zhí)行的狀態(tài)信息,稱為上下文,包括pc和寄存器文件當(dāng)前值,主存內(nèi)容等等。切換進(jìn)程時(shí),發(fā)生上下文切換。一個(gè)進(jìn)程中可以有多個(gè)線程執(zhí)行單元,每個(gè)線程都運(yùn)行在進(jìn)程的上下文中,共享同樣的代碼和數(shù)據(jù),由于網(wǎng)絡(luò)服務(wù)器等應(yīng)用對并行處理的需求越來越大,多線程模型也越來越重要。虛擬地址為每個(gè)進(jìn)程提供了一個(gè)假象,即每個(gè)進(jìn)程都在獨(dú)占主存,每個(gè)進(jìn)程看到的是一致的存儲(chǔ)器,稱為虛擬地址空間。虛擬地址空間是由大量的準(zhǔn)確定義的區(qū)構(gòu)成,linux從低地址到高地址依次為:程序代碼和數(shù)據(jù);堆;共享庫;棧;內(nèi)核虛擬存儲(chǔ)器。
總結(jié)
以上是生活随笔為你收集整理的C++程序的执行过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过分析一个C程序的汇编指令执行过程,理
- 下一篇: C++运行时候库操作概述和整个程序运行流