P2P:From Program to Process,即程序從一個(gè)項(xiàng)目變成一個(gè)進(jìn)程的過(guò)程。
做網(wǎng)站、成都網(wǎng)站設(shè)計(jì),成都做網(wǎng)站公司-創(chuàng)新互聯(lián)已向數(shù)千家企業(yè)提供了,網(wǎng)站設(shè)計(jì),網(wǎng)站制作,網(wǎng)絡(luò)營(yíng)銷等服務(wù)!設(shè)計(jì)與技術(shù)結(jié)合,多年網(wǎng)站推廣經(jīng)驗(yàn),合理的價(jià)格為您打造企業(yè)品質(zhì)網(wǎng)站。程序員通過(guò)鍵盤輸入可得hello.c(program)c語(yǔ)言源程序,hello.c在預(yù)處理器(cpp)處理后得到hello.i,通過(guò)編譯器(ccl),得到匯編程序hello.s,再通過(guò)匯編器(as),得到可重定位的目標(biāo)程序hello.o,最后通過(guò)鏈接器(ld)得到可執(zhí)行的目標(biāo)程序hello(process)。
020:From Zero-0 to Zero-0,即程序從零開(kāi)始又以零結(jié)束的過(guò)程。
在執(zhí)行程序的過(guò)程中,操作系統(tǒng)為hello分配了虛擬內(nèi)存,shell為hello創(chuàng)建了一個(gè)新的子進(jìn)程,并在這個(gè)進(jìn)程中調(diào)用execve函數(shù),加載器將hello從磁盤中加載到內(nèi)存,并將PC值設(shè)置為程序的入口,進(jìn)入 main 函數(shù)執(zhí)行目標(biāo)代碼。當(dāng)程序運(yùn)行結(jié)束后, shell 父進(jìn)程負(fù)責(zé)回收 hello 進(jìn)程,內(nèi)核刪除相關(guān)數(shù)據(jù)結(jié)構(gòu)。
1.2 環(huán)境與工具 1.2.1硬件環(huán)境 X64 CPU;2GHz;2G RAM;256GHD Disk 以上 1.2.2 軟件環(huán)境 ????? Visual Studio 2010 64位以上;CodeBlocks 64位;vi/vim/gedit+gcc 1.2.3 開(kāi)發(fā)工具 ????????????? Windows7/10 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64????????? 位/優(yōu)麒麟 64位 以上; 1.3 中間結(jié)果hello.c-程序員編寫的c語(yǔ)言源程序
hello.i-預(yù)處理后的源程序
hello.s-編譯后的匯編程序
hello.o-匯編后的可重定位的目標(biāo)文件
hello-鏈接后的可執(zhí)行文件
elf.txt- hello.o的elf格式文件
helloelf.txt- hello的elf格式文件
1.4 本章小結(jié)本節(jié)對(duì)hello的P2P和020過(guò)程進(jìn)行了大致介紹,并給出了整個(gè)過(guò)程中所使用的環(huán)境和工具及生成的中間文件。
第2章 預(yù)處理 2.1 預(yù)處理的概念與作用預(yù)處理概念:預(yù)處理器(cpp)根據(jù)以字符#開(kāi)頭的命令,修改原始的C程序。比如hello.c中第1行的#include
預(yù)處理作用:將頭文件的內(nèi)容插入到程序文本中,方便編譯器進(jìn)行下一步的編譯。
2.2在Ubuntu下預(yù)處理的命令命令:gcc -E hello.c -o hello.i
圖2.2Linux下預(yù)處理結(jié)果
2.3 Hello的預(yù)處理結(jié)果解析通過(guò)分析hello.i文件內(nèi)容,代碼變成了3091行,其中main函數(shù)占3078-3091行,文件前面插入了被#include的系統(tǒng)頭文件。
2.4 本章小結(jié)本節(jié)獲取了預(yù)處理后的hello.i文件,并據(jù)其分析了預(yù)處理的過(guò)程。
第3章 編譯 3.1 編譯的概念與作用編譯概念:編譯器(ccl)將文本文件hello.i翻譯成文本文件hello.s,它包含一個(gè)匯編語(yǔ)言程序,該程序包含函數(shù)main的定義。
編譯作用:它為不同高級(jí)語(yǔ)言的不同編譯器提供了通用的輸出語(yǔ)言。
3.2 在Ubuntu下編譯的命令命令:gcc -S hello.i -o hello.s
圖3.2Linux下編譯結(jié)果
3.3 Hello的編譯結(jié)果解析3.3.1數(shù)據(jù)
(1)字符串
只讀字符串,在.rodata中聲明
(2)數(shù)組
Main函數(shù)讀取參數(shù)時(shí),argv作為存放 char指針的數(shù)組同時(shí)是第二個(gè)參數(shù)傳入。
3.3.2賦值
使用mov指令,如圖:
movl后綴代表數(shù)據(jù)大小為4個(gè)字節(jié),將0賦值到%eax中。
3.3.3算術(shù)操作
使用算術(shù)操作指令進(jìn)行算數(shù)操作,如圖:
此處addl將%rbp-4地址處的值加了1。
3.3.4關(guān)系操作
使用 cmp指令進(jìn)行比較,如圖:
cmpl對(duì)應(yīng)源代碼i與8比較,jle代表i<=8時(shí),跳轉(zhuǎn)至L4循環(huán)體。
3.3.5函數(shù)操作
(1)參數(shù)傳遞
函數(shù)調(diào)用參數(shù)傳遞規(guī)則:第1~6個(gè)參數(shù)依次儲(chǔ)存在%rdi、%rsi、%rdx、%rcx、%r8、%r9寄存器中,剩下的參數(shù)通過(guò)棧傳遞。
(2)函數(shù)調(diào)用
使用call指令調(diào)用函數(shù),call后接函數(shù)名稱,如圖:
表示調(diào)用printf函數(shù)。
3.4 本章小結(jié)本節(jié)獲取了編譯后的hello.s文件,并據(jù)其分析了編譯的過(guò)程。
第4章 匯編 4.1 匯編的概念與作用匯編概念:匯編器(as)將hello.s翻譯成機(jī)器語(yǔ)言指令,把這些指令打包成一種叫做可重定位目標(biāo)程序的格式,并將結(jié)果保存在目標(biāo)文件hello.o中。
匯編作用:將文本文件翻譯為機(jī)器可讀懂的二進(jìn)制文件,以便于執(zhí)行鏈接。
4.2 在Ubuntu下匯編的命令gcc -c hello.s -o hello.o
圖4.2Linux下匯編結(jié)果
4.3 可重定位目標(biāo)elf格式指令:readelf -a hello.o >./elf.txt
4.3.1ELF頭
包含信息為文件結(jié)構(gòu)的說(shuō)明信息:16字節(jié)的標(biāo)識(shí)信息,文件類型,機(jī)器類型,節(jié)頭表偏移,節(jié)頭表的表項(xiàng)大小,表項(xiàng)個(gè)數(shù),生成該文件的系統(tǒng)字大小和字節(jié)順序
4.3.2節(jié)頭部表
節(jié)頭部表描述不同節(jié)的位置和大小信息,其中目標(biāo)文件的每個(gè)節(jié)都有一個(gè)固定大小的條目。
4.3.3重定位節(jié)
包含重定位的信息,鏈接時(shí)鏈接器把這個(gè)目標(biāo)文件和其他文件組合時(shí),進(jìn)行重定位并根據(jù)信息修改位置。
4.4 Hello.o的結(jié)果解析指令:objdump -d -r hello.o
操作數(shù):hello.s中操作數(shù)為十進(jìn)制,反匯編代碼中操作數(shù)為十六進(jìn)制。
分支轉(zhuǎn)移:反匯編代碼中的跳轉(zhuǎn)指令不再使用段名稱如L0、L1等,而是采用跳轉(zhuǎn)到指定地址的方式進(jìn)行跳轉(zhuǎn)。
4.5 本章小結(jié)本節(jié)獲取了匯編后的hello.o文件,并獲得ELF格式,最后分析了匯編代碼與反匯編代碼的區(qū)別。
第5章 鏈接 5.1 鏈接的概念與作用鏈接概念: C編譯器提供的標(biāo)準(zhǔn)C庫(kù)中的函數(shù)存在于一個(gè)單獨(dú)的預(yù)編譯好了的目標(biāo)文件中,鏈接器(ld)負(fù)責(zé)合并這個(gè)文件到我們的hello.o程序中。
鏈接作用:將獨(dú)立的可重定位目標(biāo)模塊組織成統(tǒng)一的可執(zhí)行目標(biā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
圖5.2Linux下匯編結(jié)果
5.3 可執(zhí)行目標(biāo)文件hello的格式命令:readelf -a hello >helloelf.txt
5.3.1ELF頭
5.3.2節(jié)頭部表
從節(jié)頭部表可以得到每個(gè)節(jié)的位置和大小信息,比如.dynsym節(jié)的開(kāi)始位置是0x400480,大小為67個(gè)字節(jié)
5.3.3程序頭
5.4 hello的虛擬地址空間圖5.4Linux系統(tǒng)edb中的hello程序
分析:從data dump中初始位置為0x401000,與5.3節(jié)中程序的入口點(diǎn).init節(jié)起始位置相同
5.5 鏈接最后分析了匯編代碼與反匯編代碼的重定位過(guò)程分析指令:objdump -d -r hello
圖5.5 hello反匯編代碼
分析:hello的反匯編代碼加入了其他庫(kù)函數(shù)(如printf),故代碼量比hello.o長(zhǎng),而且由于hello無(wú)需再重定位,因此hello中的地址為虛擬內(nèi)存地址。
鏈接過(guò)程中動(dòng)態(tài)鏈接器為函數(shù)定義了程序入口_start、初始化函數(shù)_init,_start 程序調(diào)用main函數(shù)并鏈接庫(kù)函數(shù),鏈接器將這些函數(shù)鏈接到一起使程序能夠最終執(zhí)行。
重定位過(guò)程中鏈接器首先將所有相同類型的節(jié)合并成為同一類型的新節(jié),合并完成后該新節(jié)即為可執(zhí)行文件hello的.data節(jié)。之后鏈接器再分配內(nèi)存地址賦給新的節(jié)和輸入模塊定義的節(jié)以及符號(hào)。
5.6 hello的執(zhí)行流程使用edb執(zhí)行hello,程序初始位置位于0x7f5caf5c22b0
1. 從加載到進(jìn)入main函數(shù)的過(guò)程
開(kāi)始時(shí),經(jīng)過(guò)一系列執(zhí)行,程序首先跳轉(zhuǎn)到子程序_start,該子程序位于地址4010f0處。隨后通過(guò)callq *0x2ed2(%rip) 指令跳轉(zhuǎn)到位于地址0x7f38faffefc0的“Libc-2.31.so!_libc_start_main”子程序,在子程序中,通過(guò)call *%rax指令跳轉(zhuǎn)到main函數(shù),地址為0x401125。
2. 從main函數(shù)到程序執(zhí)行完
進(jìn)入main函數(shù),程序按照源代碼順序依次執(zhí)行,在執(zhí)行的過(guò)程中分別調(diào)用不同的子程序,子程序名稱和地址如下:
401090
4010a0
4010b0
4010c0
4010d0
4010e0
首先,根據(jù)節(jié)頭部表找到GOT表地址,由圖可知其在0x403ff0。
在edb的data dump中定位0x403ff0地址
由結(jié)果可知在dl_init前后,0x403ff0 處和0x404000 處的8bit數(shù)據(jù)分別由000000000000變?yōu)榱薱07d74c57b7f 和e03299c57b7f,GOT[1]指向重定位表,作用是確定調(diào)用函數(shù)的地址,GOT[2]指向動(dòng)態(tài)鏈接器ld-linux.so運(yùn)行時(shí)地址
5.8 本章小結(jié)本節(jié)介紹了鏈接的概念和作用,同時(shí)分析了hello程序的虛擬地址空間、重定位過(guò)程、執(zhí)行流程、動(dòng)態(tài)鏈接過(guò)程。
第6章 hello進(jìn)程管理 6.1 進(jìn)程的概念與作用 ?????? 進(jìn)程概念:進(jìn)程的經(jīng)典定義就是一個(gè)執(zhí)行中程序的實(shí)例,是操作系統(tǒng)對(duì)一個(gè)正在運(yùn)行程序的抽象。 ?????? 進(jìn)程作用:進(jìn)程提供給應(yīng)用程序的關(guān)鍵抽象;一個(gè)獨(dú)立的邏輯控制流,如同程序獨(dú)占處理器;一個(gè)私有的地址空間,如同程序獨(dú)占內(nèi)存系統(tǒng) 6.2 簡(jiǎn)述殼Shell-bash的作用與處理流程作用:shell提供了一個(gè)界面,它解釋用戶輸入的命令并將它送入內(nèi)核。
處理流程:shell從終端讀入指令,將輸入的字符串切分獲得全部參數(shù),首先判斷指令是否為內(nèi)部指令,內(nèi)部指令將被執(zhí)行,否則檢查是否為一個(gè)可執(zhí)行文件。如果兩者都不是,shell將顯示一個(gè)錯(cuò)誤信息。
6.3 Hello的fork進(jìn)程創(chuàng)建過(guò)程執(zhí)行./hello后,bash解析此條命令,發(fā)現(xiàn)./hello不是bash內(nèi)置命令,于是在當(dāng)前目錄嘗試尋找并執(zhí)行hello文件。此時(shí)bash調(diào)用fork函數(shù)創(chuàng)建一個(gè)子進(jìn)程,子進(jìn)程與得到一份與父進(jìn)程用戶級(jí)虛擬空間相同且獨(dú)立的副本——包括數(shù)據(jù)段、代碼、共享庫(kù)、堆和用戶棧。二者間的PID不相同,fork函數(shù)會(huì)返回兩次,在父進(jìn)程中,返回子進(jìn)程的PID,在子進(jìn)程中,返回0。
6.4 Hello的execve過(guò)程execve開(kāi)始執(zhí)行hello有以下4個(gè)步驟:
1.刪除已存在的用戶區(qū)域。刪除當(dāng)前進(jìn)程虛擬地址的用戶部分中的已存在的區(qū)域結(jié)構(gòu)。即刪除之前shell運(yùn)行時(shí)已經(jīng)存在的區(qū)域結(jié)構(gòu)。
2.映射私有區(qū)域。為hello的代碼、數(shù)據(jù)、bss和棧區(qū)域創(chuàng)建新的區(qū)域結(jié)構(gòu)。所有這些新的區(qū)域都是私有的、寫時(shí)復(fù)制的。代碼和數(shù)據(jù)區(qū)域被映射為hello文件中的.text 和.data區(qū)。bss區(qū)域是請(qǐng)求二進(jìn)制零的,映射到匿名文件,其大小包含在hello中。棧和堆區(qū)域也是請(qǐng)求二進(jìn)制零的,初始長(zhǎng)度為零。
3.映射共享區(qū)域。hello程序與共享對(duì)象鏈接,比如標(biāo)準(zhǔn)C庫(kù)1ibc.so,那么這些對(duì)象都是動(dòng)態(tài)鏈接到這個(gè)程序的,然后再映射到用戶虛擬地址空間中的共享區(qū)域內(nèi)。
4.設(shè)置程序計(jì)數(shù)器(PC)。最后,execve設(shè)置當(dāng)前進(jìn)程上下文中的程序計(jì)數(shù)器,使之指向代碼區(qū)域的人口點(diǎn)。
6.5 Hello的進(jìn)程執(zhí)行當(dāng)我們讓它運(yùn)行hello程序時(shí),shell通過(guò)系統(tǒng)調(diào)用,來(lái)執(zhí)行我們的請(qǐng)求,系統(tǒng)調(diào)用會(huì)將控制權(quán)傳遞給操作系統(tǒng)。操作系統(tǒng)保存shell進(jìn)程的上下文,創(chuàng)建一個(gè)新的hello進(jìn)程及其上下文,然后將控制權(quán)傳給新的hello進(jìn)程。在hello進(jìn)程的執(zhí)行過(guò)程中,在某些時(shí)刻,hello程序調(diào)用sleep函數(shù)顯式請(qǐng)求進(jìn)程休眠,此時(shí)內(nèi)核執(zhí)行上下文切換,從用戶模式轉(zhuǎn)換到內(nèi)核模式,搶占hello進(jìn)程。隨后,在其他進(jìn)程執(zhí)行一段時(shí)間后,內(nèi)核做出決定將控制返回給hello進(jìn)程繼續(xù)執(zhí)行。如此反復(fù)直到hello進(jìn)程終止后,操作系統(tǒng)恢復(fù)shell進(jìn)程的上下文,并將控制權(quán)傳給它,shell進(jìn)程會(huì)繼續(xù)等待下一個(gè)命令行輸入
6.6 hello的異常與信號(hào)處理異常:hello執(zhí)行過(guò)程中會(huì)出現(xiàn)異步中斷異常和系統(tǒng)調(diào)用,中斷即來(lái)自外部I/O設(shè)備的信號(hào)打斷進(jìn)程。
信號(hào):會(huì)產(chǎn)生諸如SIGINT,SIGQUIT,SIGTSTP等信號(hào)。
運(yùn)行處理:
6.6.1不停亂按(包括回車)
只是在屏幕上顯示出來(lái)并未對(duì)程序的輸出造成影響
6.6.2輸入CTRL+Z
向內(nèi)核發(fā)送信號(hào)SINGINT,陷入到內(nèi)核態(tài),處理信號(hào),該命令為將進(jìn)程掛起并顯示處理結(jié)果。
輸入ps可查看進(jìn)程
輸入jobs列出jobs可知進(jìn)程處于停止?fàn)顟B(tài)
輸入pstree
輸入fg繼續(xù)前臺(tái)進(jìn)程
對(duì)比輸入kill前后hello進(jìn)程被殺死
6.6.3輸入CTRL+C
向內(nèi)核發(fā)送信號(hào)SINGINT,陷入到內(nèi)核態(tài),處理信號(hào),終止程序
6.7本章小結(jié)本節(jié)從進(jìn)程、異常、上下文的角度分析了hello的執(zhí)行過(guò)程,以及在執(zhí)行過(guò)程中程序?qū)Ξ惓5奶幚砹鞒獭?/p>第7章 hello的存儲(chǔ)管理 7.1 hello的存儲(chǔ)器地址空間
邏輯地址: cpu執(zhí)行程序過(guò)程中的一種中間地址。一個(gè)邏輯地址,是由一個(gè)段標(biāo)識(shí)符加上一個(gè)指定段內(nèi)的相對(duì)地址的偏移量。
線性地址:是邏輯地址到物理地址變換之間的中間層。程序代碼會(huì)產(chǎn)生邏輯地址,或者說(shuō)是段中的偏移地址,加上相應(yīng)段的基地址就生成了一個(gè)線性地址。
虛擬地址:是相對(duì)于物理內(nèi)存對(duì)整個(gè)內(nèi)存的抽象描述。有了這樣的抽象,一個(gè)程序可以使用比真實(shí)物理地址大得多的地址空間,多個(gè)進(jìn)程可以使用相同的地址。
物理地址: 用于內(nèi)存芯片級(jí)的單元尋址,與地址總線相對(duì)應(yīng)。
7.2 Intel邏輯地址到線性地址的變換-段式管理 ?????? 邏輯地址是程序源碼編譯后所形成的,跟實(shí)際內(nèi)存沒(méi)有直接聯(lián)系的地址,即在不同的機(jī)器上,使用相同的編譯器來(lái)編譯同一個(gè)源程序,則其邏輯地址是相同的。 ???? 線性地址=段基址*16+偏移的邏輯地址,而段基址由于不同的機(jī)器其任務(wù)不同,其所分配的段基址(線性地址)也會(huì)不相同,因此,其線性地址會(huì)不同。 7.3 Hello的線性地址到物理地址的變換-頁(yè)式管理線性地址對(duì)應(yīng)到物理地址是通過(guò)分頁(yè)機(jī)制,即通過(guò)頁(yè)表查找來(lái)對(duì)應(yīng)物理地址。
分頁(yè)是CPU提供的一種機(jī)制,Linux根據(jù)這種機(jī)制的規(guī)則,利用它實(shí)現(xiàn)了內(nèi)存管理。在保護(hù)模式下,控制寄存器的最高位PG位控制著分頁(yè)管理機(jī)制是否生效,如果PG=1,分頁(yè)機(jī)制生效,需通過(guò)頁(yè)表查找才能把線性地址轉(zhuǎn)換物理地址。
分頁(yè)的基本原理是把內(nèi)存劃分成大小固定的若干單元,每個(gè)單元稱為一頁(yè),每頁(yè)包含4k字節(jié)的地址空間。這樣每一頁(yè)的起始地址都是4k字節(jié)對(duì)齊的。為了能轉(zhuǎn)換成物理地址,我們需要給CPU提供當(dāng)前任務(wù)的線性地址轉(zhuǎn)物理地址的查找表,即頁(yè)表。x86將線性地址通過(guò)頁(yè)目錄表和頁(yè)表兩級(jí)查找轉(zhuǎn)換成物理地址。
7.4 TLB與四級(jí)頁(yè)表支持下的VA到PA的變換一到三級(jí)頁(yè)表中存放的數(shù)據(jù)是指向下一級(jí)頁(yè)表的首地址,而不是物理頁(yè)號(hào)。逐步訪問(wèn)到第四級(jí)頁(yè)表,第四級(jí)頁(yè)表中裝的就是物理頁(yè)號(hào),通過(guò)第四級(jí)頁(yè)表讀出的物理頁(yè)號(hào)鏈接上虛擬地址中的VPO獲得物理地址。用頁(yè)表進(jìn)行虛實(shí)地址轉(zhuǎn)化的基本原理如下圖:
7.5 三級(jí)Cache支持下的物理內(nèi)存訪問(wèn)首先是CPU發(fā)出一個(gè)虛擬地址給TLB里面搜索,如果命中的話就直接先發(fā)送到L1cache里面,沒(méi)有命中的話就先在頁(yè)表里面找到以后再發(fā)送過(guò)去,到了L1里面以后,尋找物理地址又要檢測(cè)是否命中。
7.6 hello進(jìn)程fork時(shí)的內(nèi)存映射當(dāng)fork 函數(shù)被shell調(diào)用時(shí),內(nèi)核為hello進(jìn)程創(chuàng)建各種數(shù)據(jù)結(jié)構(gòu),并分配給它一個(gè)唯一的PID 。并且創(chuàng)建hello進(jìn)程的mm_struct、區(qū)域結(jié)構(gòu)和頁(yè)表的原樣副本。它將兩個(gè)進(jìn)程中的每個(gè)頁(yè)面都標(biāo)記為只讀,并將兩個(gè)進(jìn)程中的每個(gè)區(qū)域結(jié)構(gòu)都標(biāo)記為私有的寫時(shí)復(fù)制。當(dāng)這兩個(gè)進(jìn)程中的任一一個(gè)后來(lái)進(jìn)行寫操作時(shí),寫時(shí)復(fù)制機(jī)制就會(huì)創(chuàng)建新頁(yè)面,因此,也就為每個(gè)進(jìn)程保持了私有地址空間的抽象概念。
7.7 hello進(jìn)程execve時(shí)的內(nèi)存映射1.刪除已存在的用戶區(qū)域。刪除當(dāng)前進(jìn)程虛擬地址的用戶部分中的已存在的區(qū)域結(jié)構(gòu)。即刪除之前shell運(yùn)行時(shí)已經(jīng)存在的區(qū)域結(jié)構(gòu)。
2.映射私有區(qū)域。為hello的代碼、數(shù)據(jù)、bss和棧區(qū)域創(chuàng)建新的區(qū)域結(jié)構(gòu)。所有這些新的區(qū)域都是私有的、寫時(shí)復(fù)制的。代碼和數(shù)據(jù)區(qū)域被映射為hello文件中的.text 和.data區(qū)。
3.映射共享區(qū)域。hello程序與共享對(duì)象鏈接,比如標(biāo)準(zhǔn)C庫(kù)1ibc.so,那么這些對(duì)象都是動(dòng)態(tài)鏈接到這個(gè)程序的,然后再映射到用戶虛擬地址空間中的共享區(qū)域內(nèi)。
4.設(shè)置程序計(jì)數(shù)器(PC)。最后,execve設(shè)置當(dāng)前進(jìn)程上下文中的程序計(jì)數(shù)器,使之指向代碼區(qū)域的人口點(diǎn)。
7.8 缺頁(yè)故障與缺頁(yè)中斷處理在請(qǐng)求分頁(yè)系統(tǒng)中,可以通過(guò)查詢頁(yè)表中來(lái)確定所要訪問(wèn)的頁(yè)面是否存在于內(nèi)存中。每當(dāng)所要訪問(wèn)的頁(yè)面不在內(nèi)存時(shí),會(huì)產(chǎn)生一次缺頁(yè)中斷,此時(shí)操作系統(tǒng)會(huì)根據(jù)頁(yè)表中的外存地址在外存中找到所缺的一頁(yè),并將其調(diào)入內(nèi)存。
處理:選擇一個(gè)犧牲頁(yè)面,如果這個(gè)犧牲頁(yè)面被修改過(guò),那么就將它換入新的頁(yè)面并更新頁(yè)表。當(dāng)缺頁(yè)處理程序返回時(shí),CPU 重新啟動(dòng)引起缺頁(yè)的指令。
7.9動(dòng)態(tài)存儲(chǔ)分配管理在程序運(yùn)行時(shí)程序員使用動(dòng)態(tài)內(nèi)存分配器獲得虛擬內(nèi)存,動(dòng)態(tài)內(nèi)存分配器維護(hù)著一個(gè)進(jìn)程的虛擬內(nèi)存區(qū)域,稱為堆。分配器將堆視為一組不同大小的塊的集合,每個(gè)塊要么是已分配的,要么是空閑的。分配器的類型有顯示分配和隱式分配,前者要求應(yīng)用顯式地釋放任何已分配的塊,后者應(yīng)用檢測(cè)到已分配塊不再被程序所使用,就釋放這個(gè)塊。
7.10本章小結(jié)本節(jié)分析了hello的存儲(chǔ)器空間,并給出了 TLB與四級(jí)頁(yè)表支持下的VA與 PA的變換和三級(jí)Cache支持下的物理內(nèi)存訪問(wèn)過(guò)程的介紹。
第8章 hello的IO管理 8.1 Linux的IO設(shè)備管理方法設(shè)備的模型化:文件
設(shè)備管理:unix io接口
所有的I/ O 設(shè)備(例如網(wǎng)絡(luò)、磁盤和終端)都被模型化為文件,而所有的輸入和輸出都被當(dāng)作對(duì)相應(yīng)文件的讀和寫來(lái)執(zhí)行。這種將設(shè)備映射為文件的方式,允許Linux 內(nèi)核引出一個(gè)簡(jiǎn)單、低級(jí)的應(yīng)用接口,稱為Unix I/O,這使得所有的輸入和輸出都能以一種統(tǒng)一且一致的方式來(lái)執(zhí)行,這就是Unix I/O接口。
8.2 簡(jiǎn)述Unix IO接口及其函數(shù)Linux/unix IO接口:
函數(shù):
Open()-打開(kāi)一個(gè)已經(jīng)存在的文件或是創(chuàng)建一個(gè)新文件
Read()-從文件讀取數(shù)據(jù),執(zhí)行輸出
Write()-從文件中讀取數(shù)據(jù),執(zhí)行輸出
Close()-關(guān)閉一個(gè)被打開(kāi)的文件
Lseek()-用于在指定的文件描述符中將文件指針定位到相應(yīng)位置
8.3 printf的實(shí)現(xiàn)分析printf()函數(shù)將變長(zhǎng)參數(shù)的指針arg作為參數(shù),傳給vsprintf函數(shù)。然后vsprintf函數(shù)解析格式化字符串,調(diào)用write()函數(shù)。在write函數(shù)中,將棧中參數(shù)放入寄存器,ecx是字符個(gè)數(shù),ebx存放第一個(gè)字符地址,最后,write函數(shù)調(diào)用syscall(int INT_VECTOR_SYS_CALL)。syscall將字符串中的字節(jié)從寄存器中通過(guò)總線復(fù)制到顯卡的顯存中,顯存中存儲(chǔ)的是字符的ASCII碼。字符顯示驅(qū)動(dòng)子程序?qū)⑼ㄟ^(guò) ASCII 碼在字模庫(kù)中找到點(diǎn)陣信息將點(diǎn)陣信息存 儲(chǔ)到 vram 中。顯示芯片會(huì)按照一定的刷新頻率逐行讀取 vram,并通過(guò)信號(hào)線向液晶顯示器傳輸每一個(gè)點(diǎn)(RGB 分量),最終打印出了我們需要的字符串。
8.4 getchar的實(shí)現(xiàn)分析異步異常-鍵盤中斷的處理:鍵盤中斷處理子程序。接受按鍵掃描碼轉(zhuǎn)成ascii碼,保存到系統(tǒng)的鍵盤緩沖區(qū)。
getchar等調(diào)用read系統(tǒng)函數(shù),通過(guò)系統(tǒng)調(diào)用讀取按鍵ascii碼,直到接受到回車鍵才返回。
8.5本章小結(jié)本節(jié)主要介紹了 Linux 的 IO 設(shè)備管理方法、Unix IO 接口及其函數(shù),簡(jiǎn)單分析了 printf 函數(shù)和 getchar 函數(shù)的實(shí)現(xiàn)。
結(jié)論hello程序所經(jīng)歷的過(guò)程:
1.編寫:程序員通過(guò)鍵盤輸入可得hello.c(program)c語(yǔ)言源程序。
2.預(yù)處理:hello.c在預(yù)處理器(cpp)處理后得到hello.i。
3.編譯:通過(guò)編譯器(ccl),得到匯編程序hello.s。
4.匯編:通過(guò)匯編器(as),得到可重定位的目標(biāo)程序hello.o。
5.鏈接:通過(guò)鏈接器(ld)得到可執(zhí)行的目標(biāo)程序hello(process)。
6.運(yùn)行:在shell命令行輸入./hello 2021112660 孫吳錫 3運(yùn)行程序。
7.創(chuàng)建子進(jìn)程:shell調(diào)用fork函數(shù)創(chuàng)建子進(jìn)程。
8.運(yùn)行程序:調(diào)用execve將程序加載進(jìn)去。
9.結(jié)束:shell父進(jìn)程回收子進(jìn)程,內(nèi)核刪除為這個(gè)進(jìn)程創(chuàng)建的所有數(shù)據(jù)結(jié)構(gòu)。
感悟:
即使最簡(jiǎn)單的一個(gè)hello程序,其執(zhí)行處理的過(guò)程也是非常復(fù)雜的,要想真正理解他要花費(fèi)很大的功夫,我從中學(xué)到了預(yù)處理、編譯、匯編、鏈接、進(jìn)程管理、存儲(chǔ)管理、IO管理的相關(guān)知識(shí),這次的課程讓我獲益匪淺。
附件列出所有的中間產(chǎn)物的文件名,并予以說(shuō)明起作用。
hello.c-程序員編寫的c語(yǔ)言源程序
hello.i-預(yù)處理后的源程序
hello.s-編譯后的匯編程序
hello.o-匯編后的可重定位的目標(biāo)文件
hello-鏈接后的可執(zhí)行文件
elf.txt- hello.o的elf格式文件
helloelf.txt- hello的elf格式文件
參考文獻(xiàn)[1]? 林來(lái)興. 空間控制技術(shù)[M]. 北京:中國(guó)宇航出版社,1992:25-42.
[2]? 辛希孟. 信息技術(shù)與信息服務(wù)國(guó)際研討會(huì)論文集:A集[C]. 北京:中國(guó)科學(xué)出版社,1999.
[3]? 趙耀東. 新時(shí)代的工業(yè)工程師[M/OL]. 臺(tái)北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
[4]? 諶穎. 空間交會(huì)控制理論與方法研究[D]. 哈爾濱:哈爾濱工業(yè)大學(xué),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.
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站題目:程序人生-Hello’sP2P-創(chuàng)新互聯(lián)
標(biāo)題網(wǎng)址:http://aaarwkj.com/article34/issse.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、建站公司、企業(yè)建站、虛擬主機(jī)、手機(jī)網(wǎng)站建設(shè)、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容