第一章
預(yù)處理階段->得到.i文件->編譯階段->得到.s文件->匯編階段->得到.o文件(二進(jìn)制文件)->鏈接階段
優(yōu)點(diǎn):優(yōu)化程序性能辩恼、理解鏈接時(shí)出現(xiàn)的錯(cuò)誤点晴、避免安全漏洞锉走。
系統(tǒng)硬件的組成:1.總線癌瘾、2.I/O設(shè)備记劈、3.主存、4.處理器
CPU指令:加載、存儲(chǔ)浓镜、操作溃列、跳轉(zhuǎn)
進(jìn)程的虛擬空間組成:程序代碼和數(shù)據(jù)、堆膛薛、共享庫听隐、棧、內(nèi)核虛擬內(nèi)存哄啄。
第二章 信息的表示和處理
2.1 信息存儲(chǔ)
2.1.1 十六進(jìn)制表示法
2.1.2 字?jǐn)?shù)據(jù)大小
2.1.3 尋址和字節(jié)順序
小端法:最低有效字節(jié)在最前面雅任。
大端法:最高有效字節(jié)在最前面。
個(gè)人理解:大端咨跌,正常方向沪么;小端,反向锌半。
2.1.4 表示字符串
C語言中禽车,字符串被編碼為一個(gè)以NULL(其值為0)字符結(jié)尾的字符數(shù)組。每個(gè)字符都由某個(gè)標(biāo)準(zhǔn)編碼來表示拳喻,最常見的是ASCII字符碼哭当。
2.1.5 表示代碼
2.1.6 布爾代數(shù)簡介
& - 當(dāng)兩邊值都為1時(shí)結(jié)果才為1,其余情況都是0
| - 當(dāng)兩邊值有一個(gè)是1冗澈,結(jié)果就為1钦勘。
^ - 兩邊值不同為1,相同為0亚亲。
~ - 兩邊取反
2.1.7 C語言中的位級運(yùn)算
2.1.8 C語言中的邏輯運(yùn)算
TRUE==》1
FALSE==》0
邏輯運(yùn)算&&和||與它們對應(yīng)的位級運(yùn)算&和|之間第二個(gè)重要區(qū)別彻采,如果對第一個(gè)參數(shù)求值就能確定表達(dá)式的結(jié)果,那么邏輯運(yùn)算符就不會(huì)對第二個(gè)參數(shù)求值捌归。
2.1.9 C語言中的移位運(yùn)算
<<左移:該值從右開始肛响,向左移動(dòng)4位,丟棄左邊最高k個(gè)數(shù)字惜索,右邊添加4個(gè)0
>>邏輯右移:左邊補(bǔ)k個(gè)0特笋,右邊k個(gè)數(shù)字舍棄
>>算術(shù)右移:左邊補(bǔ)k個(gè)1(注意:這里是最高位是多少填充多少),右邊k個(gè)數(shù)字舍棄
默認(rèn)使用算術(shù)右移巾兆,但是無符號數(shù)是邏輯右移猎物。
2.2 整數(shù)表示
2.2.1 整數(shù)數(shù)據(jù)類型
2.2.2 無符號數(shù)的編碼:
個(gè)人理解:這個(gè)公式其實(shí)就是把二進(jìn)制數(shù)轉(zhuǎn)成十進(jìn)制數(shù)。
2.2.3 補(bǔ)碼編碼:
個(gè)人理解:簡單的說就是在最高位添加了個(gè)符號位角塑。
原理:補(bǔ)碼編碼的唯一性蔫磨。
2.2.4 有符號數(shù)和無符號數(shù)之間的轉(zhuǎn)換:
C語言允許在各種不同的數(shù)字?jǐn)?shù)據(jù)類型之間做強(qiáng)制類型轉(zhuǎn)換。
2.2.5 C語言中的有符號數(shù)與無符號數(shù)
盡管c語言標(biāo)準(zhǔn)沒有指定有符號數(shù)要采用某種表示圃伶,但是幾乎所有的機(jī)器都是用補(bǔ)碼蚁袭。通常,大多數(shù)數(shù)字都默認(rèn)為是有符號的膛锭。
2.2.6 擴(kuò)展一個(gè)數(shù)字的位表示
2.2.7 截?cái)鄶?shù)字
2.2.8 關(guān)于有符號數(shù)和無符號數(shù)的建議
2.3 整數(shù)運(yùn)算
個(gè)人理解:這里主要以數(shù)學(xué)公式的形式講述了整數(shù)的運(yùn)算。
2.3.1 無符號加法
2.3.2 補(bǔ)碼加法
2.3.3 補(bǔ)碼的非
2.3.4 無符號乘法
2.3.5 補(bǔ)碼乘法
2.3.6 乘以常數(shù)
注意:無論是無符號運(yùn)算還是補(bǔ)碼運(yùn)算蝗岖,乘以2的冪都可能會(huì)導(dǎo)致溢出。
2.3.7 除以2的冪
2.3.8 關(guān)于整數(shù)運(yùn)算的最后思考
個(gè)人理解榔至,關(guān)于整數(shù)的相關(guān)運(yùn)算規(guī)則剪侮。
2.4 浮點(diǎn)數(shù)
2.4.1 二進(jìn)制小數(shù)
2.4.2 IEEE浮點(diǎn)表示
情況1:當(dāng)exp的位模式既不全為0(數(shù)值0),也不全為1(單精度數(shù)組為255洛退,雙精度數(shù)值為2047)
情況2:當(dāng)補(bǔ)碼域?yàn)槿?時(shí)
情況3:當(dāng)指階碼全為1的時(shí)候出現(xiàn)
2.4.3 數(shù)字示例
2.4.4 舍入
2.4.5 浮點(diǎn)運(yùn)算
2.4.6 C語言中的浮點(diǎn)數(shù)
第三章 程序的機(jī)器級表示
個(gè)人理解:該章節(jié)主要講了匯編,我們寫的c代碼是如何翻譯成匯編語言到機(jī)器的寄存器的杰标,沒學(xué)過匯編兵怯,前部分還好,后面看不來腔剂。
3.1 歷史觀點(diǎn)
3.2 程序編碼
3.2.1 機(jī)器級代碼
● 程序計(jì)數(shù)器(通常成為“PC”媒区,在x86-64中用%rip表示)給出將要執(zhí)行的下一條指令在內(nèi)存中的地址。
● 整數(shù)寄存器文件包含16個(gè)命名的位置掸犬,分別存儲(chǔ)64位的值袜漩。這些寄存器可以存儲(chǔ)地址(對應(yīng)于C語言的指針)或整數(shù)數(shù)據(jù)。有的寄存器被用來記錄某些重要的程序狀態(tài)湾碎,而其他的寄存器用來保存臨時(shí)數(shù)據(jù)宙攻,例如過程的參數(shù)和局部變量,以及函數(shù)的返回值介褥。
● 條件碼寄存器保存著最近執(zhí)行的算術(shù)或邏輯指令的狀態(tài)信息座掘。它們用來實(shí)現(xiàn)控制或數(shù)據(jù)流中的條件變化,比如說用來實(shí)現(xiàn)if和while語句柔滔。
● 一組向量寄存器可以存放一個(gè)或多個(gè)整數(shù)或浮點(diǎn)數(shù)值溢陪。
3.2.2 代碼示例
在命令行上使用“-S”選項(xiàng),就能看到C語言編譯器產(chǎn)生的匯編代碼
linux>gcc -Og -S xxx.c
使用“-C”命令行選項(xiàng)睛廊,GCC會(huì)編譯并匯編該代碼
linux>gcc -Og -C xxx.c
這樣會(huì)產(chǎn)生目標(biāo)代碼文件xxx.o形真,它是二進(jìn)制格式的,無法直接查看超全。要查看機(jī)器代碼文件的內(nèi)容咆霜,有一類成為反匯編器的程序非常有用。在Linux系統(tǒng)中卵迂,帶“-d”命令行標(biāo)識(shí)的程序OBJDUMP可以充當(dāng)這個(gè)角色裕便。
linux>objdump -d xxx.o
3.2.3 關(guān)于格式的注解
3.3 數(shù)據(jù)格式
3.4 訪問信息
3.4.1 操作數(shù)指示符
大多數(shù)指令有一個(gè)或多個(gè)操作數(shù),指示出執(zhí)行一個(gè)操作中要使用的源數(shù)據(jù)值见咒,以及放置結(jié)果的目的位置偿衰。
各種不同的操作數(shù)的可能性被分為三種類型
立即數(shù):用來表示常數(shù)值。
寄存器:表示某個(gè)寄存器的內(nèi)容。
內(nèi)存引用:根據(jù)計(jì)算出來的地址訪問某個(gè)內(nèi)存位置下翎。
3.4.2 數(shù)據(jù)傳送指令
3.4.3 數(shù)據(jù)傳送示例
3.4.4 壓入和探出棧數(shù)據(jù)
3.5 算術(shù)和邏輯操作
3.5.1 有效加載地址
3.5.2 一元和二元操作
3.5.3 移位操作
3.5.4 討論
3.5.5 特殊的算術(shù)操作
3.6 控制
3.6.1 條件碼
3.6.2 訪問條件碼
條件碼讀取三種方法:
1.根據(jù)條件碼的某種組合缤言,將一個(gè)字節(jié)設(shè)置為0或者1
2.可以條件跳轉(zhuǎn)到程序的某個(gè)其他的部分
3.可以有條件地傳送數(shù)據(jù)。
3.6.3 跳轉(zhuǎn)指令
3.6.4 跳轉(zhuǎn)指令的編碼
3.6.5 用條件控制來實(shí)現(xiàn)條件分支
將條件表達(dá)式和語句從C語言翻譯成機(jī)器代碼视事,最常用的方式是結(jié)合有條件和無條件跳轉(zhuǎn)胆萧。
3.6.6 用條件傳送來實(shí)現(xiàn)條件分支
3.6.7 循環(huán)
3.6.8 switch語句
3.7 過程
3.7.1 運(yùn)行時(shí)棧
3.7.2 轉(zhuǎn)移控制
3.7.3 數(shù)據(jù)傳送
3.7.4 棧上的局部存儲(chǔ)
3.7.5 寄存器中的局部存儲(chǔ)空間
3.7.6 遞歸過程
3.8 數(shù)組分配和訪問
第四章 處理器體系結(jié)構(gòu)
4.1 Y86-64 指令集體系結(jié)構(gòu)
4.1.1 程序員的可見狀態(tài)
4.1.2 Y86-64指令
● x86-64的movq指令分成了4個(gè)不同的指令:irmovq、rrmovq俐东、mrmovq跌穗、rmmovq,分別顯示地指明源和目的的格式虏辫。源可以是立即數(shù)i蚌吸,寄存器r或內(nèi)存m。第一個(gè)字母表示源的類型砌庄,第二個(gè)字母表示目的的類型羹唠。
● 有4個(gè)整數(shù)操作指令,他們是addq娄昆、subq佩微、andq和xorq,它們只對寄存器數(shù)據(jù)進(jìn)行操作萌焰,而x86-64還允許對內(nèi)存數(shù)據(jù)進(jìn)行這些操作哺眯。這些指令會(huì)設(shè)置3個(gè)條件碼ZF、SF和OF(零杆怕、符號族购、溢出)。
● 7個(gè)跳轉(zhuǎn)指令陵珍,jmp寝杖、jle、jl互纯、je瑟幕、jne、jge和jg留潦。
● 6個(gè)條件傳送指令只盹,cmovle、cmovl兔院、cmove殖卑、comvne、cmovge和comvg坊萝。
● call指令將返回地址入棧孵稽,然后調(diào)到目的地址许起。
● ret指令從這樣的調(diào)用中返回。
● pushq和popq指令實(shí)現(xiàn)了入棧和出棧菩鲜。
● halt指令停止指令的執(zhí)行园细。
4.1.3 指令編碼
4.1.4 Y86-64異常
4.1.5 Y86-64程序
4.1.6 Y86-64指令的詳情
4.2 邏輯設(shè)計(jì)和硬件控制語言HCL
4.2.1 邏輯門
4.2.2 組合電路和HCL布爾表達(dá)式
4.2.3 字級的組合電路和HCL整數(shù)表達(dá)式
4.2.4 集合關(guān)系
4.2.5 存儲(chǔ)器和時(shí)鐘
4.3 Y86-64的順序?qū)崿F(xiàn)
4.3.1 將處理組織成階段
4.3.2 SEQ硬件結(jié)構(gòu)
4.3.3 SEQ時(shí)序
4.3.4 SEQ階段的實(shí)現(xiàn)
1.取指階段
2.譯碼和寫回階段
3.執(zhí)行階段
4.訪存階段
5.更新PC階段
4.4 流水線的通用原理
4.4.1 計(jì)算流水線
4.4.2 流水線操作的詳細(xì)說明
4.4.3 流水線的局限性
1.不一致的劃分
2.流水線過深,收益反而下降
4.4.4 帶反饋的流水線系統(tǒng)
4.5 Y86-64流水線的實(shí)現(xiàn)
4.5.1 SEQ+:重新安排計(jì)算階段
4.5.2 插入流水線寄存器
第五章 優(yōu)化程序性能
5.9 提高并行性
5.9.1 多個(gè)累計(jì)變量
對于一個(gè)可結(jié)合和可交換的合并運(yùn)算來說接校,比如說整數(shù)加法或乘法猛频,我們可以將一組合并運(yùn)算分割成兩個(gè)或更多的部分,并在最后合并結(jié)果來提高性能蛛勉。
5.9.2 重新結(jié)合變換
5.10 優(yōu)化合并代碼的結(jié)果小結(jié)
5.11 一些限制因素
5.11.1 寄存器溢出
循環(huán)并行性的好處受匯編代碼描述計(jì)算的能力限制鹿寻。如果我們的并行度p超過了可用的寄存器數(shù)量,那么編譯器會(huì)訴諸溢出诽凌,將某些臨時(shí)值存放到內(nèi)存中烈和,通常是在運(yùn)行時(shí)堆棧上分配空間。
一旦編譯器必須要訴諸溢出皿淋,那么維護(hù)多個(gè)累積變量的優(yōu)勢就很可能消失。幸運(yùn)的是恬试,x86-64有足夠多的寄存器窝趣,大多數(shù)循環(huán)在出現(xiàn)寄存器溢出之前就將達(dá)到吞吐量限制。
5.11.2 分支預(yù)測和預(yù)測錯(cuò)誤處罰
當(dāng)分支預(yù)測邏輯不能正確預(yù)測一個(gè)分支是否要跳轉(zhuǎn)的時(shí)候训柴,條件分支可能會(huì)招致很大的預(yù)測錯(cuò)誤處罰哑舒。
- 不要過分關(guān)心可預(yù)測的分支
- 書寫適合用條件傳送實(shí)現(xiàn)的代碼
5.12 理解內(nèi)存性能
5.12.1 加載的性能
5.12.1 存儲(chǔ)的性能
5.13 應(yīng)用:性能提高技術(shù)
- 高級設(shè)計(jì),為遇到的問題選擇適當(dāng)?shù)乃惴ê蛿?shù)據(jù)結(jié)構(gòu)幻馁。
- 基本編碼原則洗鸵。避免限制優(yōu)化的因素,這樣編譯器就能產(chǎn)生高效的代碼仗嗦。
消除連續(xù)的函數(shù)調(diào)用膘滨。
消除不必要的內(nèi)存引用 - 低級優(yōu)化,結(jié)構(gòu)化代碼以利用硬件功能
展開循環(huán)稀拐,降低開銷火邓,并且使得進(jìn)一步的優(yōu)化成為可能。
通過使用例如多個(gè)累計(jì)變量和重新結(jié)合等技術(shù)德撬,找到方法提高指令級并行铲咨。
用功能性的風(fēng)格重寫條件操作,使得編譯采用條件數(shù)據(jù)傳送蜓洪。
5.14 確認(rèn)和消除性能瓶頸
5.14.1 程序剖析
第六章 存儲(chǔ)器層次結(jié)構(gòu)
6.1 存儲(chǔ)技術(shù)
6.1.1 隨機(jī)訪問存儲(chǔ)器
- 靜態(tài)RAM:SRAM將每個(gè)位存儲(chǔ)在一個(gè)雙穩(wěn)態(tài)的存儲(chǔ)器單元里纤勒,每個(gè)單元是用一個(gè)六晶體管電路來實(shí)現(xiàn)的。他可以無限期地保持在兩個(gè)不同的電壓配置或狀態(tài)之一隆檀。由于SRAM存儲(chǔ)器單元的雙穩(wěn)態(tài)特性摇天,只要有電粹湃,他就會(huì)永遠(yuǎn)地保存它的值。即使有干擾來擾亂電壓闸翅,當(dāng)干擾消除時(shí)再芋,電路就會(huì)恢復(fù)到穩(wěn)定值。
- 動(dòng)態(tài)RAM
DRAM將每個(gè)位存儲(chǔ)為對一個(gè)電容的充電坚冀。這個(gè)電容非常小济赎,通常只有大約30毫微微法拉——30*10-15法拉。
3.傳統(tǒng)的DRAM
DRAM芯片中的單元(位)被分成d個(gè)超單元记某,每個(gè)超單元都由w個(gè)DRAM單元組成司训。一個(gè)dxw的DRAM總共存儲(chǔ)了dw位信息。 - 內(nèi)存模塊
DRAM芯片封裝在內(nèi)存模塊中液南,它查到主板的擴(kuò)展槽上壳猜。 - 增強(qiáng)的DRAM
快頁模式
擴(kuò)展數(shù)據(jù)輸出
同步DRAM
雙倍數(shù)據(jù)速率同步
視頻RAM - 非易失性存儲(chǔ)器
非易失性存儲(chǔ)器即使在關(guān)電之后,仍然保存著它們的信息滑凉。 - 訪問主存
6.1.2 磁盤存儲(chǔ)
-
磁盤構(gòu)造
-
磁盤容量
- 磁盤操作
- 邏輯磁盤塊
- 連接I/O設(shè)備
- 訪問磁盤
6.1.3 固態(tài)硬盤
6.1.4 存儲(chǔ)技術(shù)趨勢
6.2 局限性
6.2.1 對程序數(shù)據(jù)引用的局部性
6.2.2 取指令的局部性
6.2.3 局部性小結(jié)
6.3 存儲(chǔ)器層次結(jié)構(gòu)
6.3.1 存儲(chǔ)器層次結(jié)構(gòu)中的緩存
1.緩存命中
2.緩存不命中
3.緩存不命中的種類
4.緩存管理
6.3.2 存儲(chǔ)器層次結(jié)構(gòu)概念小結(jié)
6.4 高速緩存存儲(chǔ)器
6.4.1 通用的高速緩存存儲(chǔ)器組織結(jié)構(gòu)
6.4.2 直接映射高速緩存
6.4.3 組相聯(lián)高速緩存
6.4.4 全相聯(lián)高速緩存
6.4.5 有關(guān)寫的問題
6.4.6 一個(gè)真實(shí)的高速緩存層次結(jié)構(gòu)的解剖
6.4.7 高速緩存參數(shù)的性能影響
6.5 編寫高速緩存友好的代碼
6.6 綜合:高速緩存對程序性能的影響
6.6.1 存儲(chǔ)器山
一個(gè)程序從存儲(chǔ)系統(tǒng)中讀數(shù)據(jù)的速率成為度吞吐量统扳,或者有時(shí)成為讀帶寬。
6.6.2 重新排列循環(huán)以提高空間局部性
6.6.3 在程序中利用局部性
- 將你的注意力集中在內(nèi)循環(huán)上畅姊,大部分計(jì)算和內(nèi)存訪問都發(fā)生在這里咒钟。
- 通過按照數(shù)據(jù)對象存儲(chǔ)在內(nèi)存中的順序,以步長為1的來讀數(shù)據(jù)若未,從而使得你程序中的空間局部性最大朱嘴。
- 一旦從存儲(chǔ)器中讀入了一個(gè)數(shù)據(jù)對象,就盡可能多地使用它粗合,從而使得程序中的時(shí)間局部性最大萍嬉。
6.7 小結(jié)
第七章 鏈接
7.1 編譯器驅(qū)動(dòng)程序
大多數(shù)編譯系統(tǒng)提供編譯器驅(qū)動(dòng)程序,它代表用戶在需要時(shí)調(diào)用語言預(yù)處理器隙疚、編譯器壤追、匯編器和鏈接器。
驅(qū)動(dòng)程序首先運(yùn)行C預(yù)處理器供屉,它將C的源代碼翻譯成一個(gè)ASCII碼的中間文件大诸,接下來,驅(qū)動(dòng)程序運(yùn)行C編譯器贯卦,它將該文件翻譯成一個(gè)ASCII匯編語言文件资柔,然后驅(qū)動(dòng)程序運(yùn)行匯編器,在翻譯成一個(gè)可重定位目標(biāo)文件撵割。最后贿堰,它運(yùn)行鏈接器程序id,將一些必要的系統(tǒng)目標(biāo)文件組合起來啡彬,創(chuàng)建一個(gè)可執(zhí)行目標(biāo)文件prog羹与。要運(yùn)行prog故硅,只要輸入./prog,shell調(diào)用操作系統(tǒng)中一個(gè)叫做加載器的函數(shù)纵搁,它將可執(zhí)行文件prog中的代碼和數(shù)據(jù)復(fù)制到內(nèi)存吃衅,然后將控制轉(zhuǎn)移到這個(gè)程序的開頭。
7.2 靜態(tài)鏈接
7.3 目標(biāo)文件
7.4 可重定位目標(biāo)文件
7.5 符號和符號表
7.6 符號解析
7.6.1 鏈接器如何解析多重定義的全局符號
7.6.2 與靜態(tài)庫鏈接
7.6.3 鏈接器如何使用靜態(tài)庫來解析引用
7.7 重定位
7.7.1 重定位條目
7.7.2 重定位符號引用
- 重定位PC相對引用
- 重定位PC絕對引用
7.8 可執(zhí)行目標(biāo)文件
7.9 加載可執(zhí)行目標(biāo)文件
7.10 動(dòng)態(tài)鏈接共享庫
7.11 從應(yīng)用程序中加載和鏈接共享庫
7.12 位置無關(guān)代碼
- PIC數(shù)據(jù)引用
-
PIC函數(shù)調(diào)用
7.13 庫打樁機(jī)制
7.13.1 編譯時(shí)打樁
7.13.2 鏈接時(shí)打樁
7.13.3 運(yùn)行時(shí)打樁
7.14 處理目標(biāo)文件的工具
7.15 小結(jié)
第八章 異常流控制
8.1 異常
異常就是控制流中的突變腾誉,用來相應(yīng)處理器狀態(tài)中的某些變化徘层。
8.1.1 異常處理
8.1.2 異常的類別
8.1.3 Linux/x86-64 系統(tǒng)中的異常
- Linux/x86-64 故障和終止
-
Linux/x86-64系統(tǒng)調(diào)用
8.2 進(jìn)程
進(jìn)程提供給應(yīng)用程序的關(guān)鍵抽象
一個(gè)獨(dú)立的邏輯控制流,它提供了一個(gè)假象利职,好像我們的程序獨(dú)占地使用處理器趣效。
一個(gè)私有的地址控件,它提供了一個(gè)假象猪贪,好像我們的程序獨(dú)占地使用內(nèi)存系統(tǒng)跷敬。
8.2.1 邏輯控制流
8.2.2 并發(fā)流
8.2.3 私有地址空間
8.2.4 用戶模式和內(nèi)核模式
8.2.5 上下文切換
內(nèi)核為每個(gè)進(jìn)程維持一個(gè)上下文,上下文就是內(nèi)核重新啟動(dòng)一個(gè)被搶占的進(jìn)程所需的狀態(tài)热押。它由一些對象的值組成西傀,這些對象包括通用目的寄存器、浮點(diǎn)寄存器桶癣、程序計(jì)數(shù)器池凄、用戶棧、狀態(tài)寄存器鬼廓、內(nèi)核棧和各種內(nèi)核數(shù)據(jù)結(jié)構(gòu),比如描述地址控件的頁表致盟、包含有關(guān)當(dāng)前進(jìn)程信息的進(jìn)程表碎税,以及包含進(jìn)程已打開文件的信息的文件表。
8.3 系統(tǒng)調(diào)用錯(cuò)誤處理
8.4 進(jìn)程控制
8.4.1 獲取進(jìn)程ID
8.4.2 創(chuàng)建和終止進(jìn)程
8.4.3 回收子線程
- 判定等待集合的成員
- 修改默認(rèn)行為
- 檢查已回收子進(jìn)程的退出狀態(tài)
- 錯(cuò)誤條件
- wait函數(shù)
- 使用waitpid的示例
8.4.4 讓進(jìn)程休眠
8.4.5 加載并運(yùn)行程序
8.4.6 利用fork和execve運(yùn)行程序
8.5 信號
8.5.1 信號術(shù)語
8.5.2 發(fā)送信號
- 進(jìn)程組
- 用/bin/kill 程序發(fā)送信號
- 從鍵盤發(fā)送信號
- 用kill函數(shù)發(fā)送信號
- 用alarm函數(shù)發(fā)送信號
8.5.3 接收信號
8.5.4 阻塞和解除阻塞信號
8.5.5 編寫信號處理程序
- 安全的信號處理
- 正確的信號處理
- 可移植的信號處理
8.5.6 同步流以避免討厭的并發(fā)錯(cuò)誤
8.5.7 顯式地等待信號
8.6 非本地跳轉(zhuǎn)
8.7 操作進(jìn)程的工具
8.8 小結(jié)
第九章 虛擬內(nèi)存
9.1 物理和虛擬尋址
9.2 地址空間
9.3 虛擬內(nèi)存作為緩存的工具
9.3.1 DRAM緩存的組織結(jié)構(gòu)
9.3.2 頁表
9.3.3 頁命中
9.3.4 缺頁
9.3.5 分配頁面
9.3.6 又是局部性救了我們
9.4 虛擬內(nèi)存作為內(nèi)存管理的工具
9.5 虛擬內(nèi)存作為內(nèi)存保護(hù)的工具
9.6 地址翻譯
9.6.1 結(jié)合高速緩存和虛擬內(nèi)存
9.6.2 利用TLB加速地址翻譯
9.6.3 多級頁表
9.6.4 綜合:端到端的地址翻譯
9.7 案例研究:Intel Core i7/Linux 內(nèi)存系統(tǒng)
9.7.1 Core i7地址翻譯
9.7.2 Linux虛擬內(nèi)存系統(tǒng)
- Linux虛擬內(nèi)存區(qū)域
- Linux缺頁異常處理
9.8 內(nèi)存映射
9.8.1 在看共享對象
9.8.2 再看fork函數(shù)
9.8.3 再看execve函數(shù)
9.8.4 使用mmap函數(shù)的用戶級內(nèi)存映射
9.9 動(dòng)態(tài)內(nèi)存分配
9.9.1 malloc 和 free 函數(shù)
9.9.2 為什么要使用動(dòng)態(tài)內(nèi)存分配
9.9.3 分配器的要求和目標(biāo)
目標(biāo)1.最大化吞吐率
目標(biāo)2.最大化內(nèi)存利用率
9.9.4 碎片
9.9.5 實(shí)現(xiàn)問題
9.9.6 隱式空閑鏈表
9.9.7 放置已分配的塊
9.9.8 分割空閑塊
9.9.9 獲取額外的堆內(nèi)存
9.9.10 合并空閑塊
9.9.11 帶邊界標(biāo)記的合并
9.9.12 綜合:實(shí)現(xiàn)一個(gè)簡單的分配器
- 通用分配器設(shè)計(jì)
- 操作空閑鏈表的基本常數(shù)和宏
- 創(chuàng)建初始空閑鏈表
- 釋放和合并塊
- 分配塊
9.9.13 顯式空閑鏈表
9.9.14 分離的空閑鏈表
- 簡單分離存儲(chǔ)
- 分離適配
- 伙伴系統(tǒng)
9.10 垃圾收集
9.10.1 垃圾收集器的基本知識(shí)
9.10.2 Mark&Sweep垃圾收集器
9.10.3 C程序的保守Mark & Sweep
9.11 C程序中常見的與內(nèi)存有關(guān)的錯(cuò)誤
9.11.1 間接引用壞指針
9.11.2 讀未初始化的內(nèi)存
9.11.3 允許棧緩沖區(qū)溢出
9.11.4 假設(shè)指針和它們指向的對象是相同大小的
9.11.5 造成錯(cuò)位錯(cuò)誤
9.11.6 引用指針,而不是它所指向的對象
9.11.7 誤解指針運(yùn)算
9.11.8 引用不存在的變量
9.11.9 引用空閑堆塊中的數(shù)據(jù)
9.12 小結(jié)
第十章 系統(tǒng)級I/O
10.1 Unix I/O
打開文件
Linux shell創(chuàng)建的每個(gè)進(jìn)程開始時(shí)都有三個(gè)打開的文件
改變當(dāng)前的文件位置
讀寫文件
關(guān)閉文件
10.2 文件
普通文件包含任意數(shù)據(jù)
目錄是包含一組鏈接的文件,其中每個(gè)鏈接都將一個(gè)文件名映射到一個(gè)文件顶瞒,這個(gè)文件可能是另一個(gè)目錄
套接字是用來與另一個(gè)進(jìn)程進(jìn)行跨網(wǎng)絡(luò)通信的文件
10.3 打開和關(guān)閉文件
10.4 讀和寫文件
10.5 用RIO包健壯地讀寫
- 無緩沖的輸入輸出函數(shù)
- 帶緩沖的輸入函數(shù)
10.6 讀取文件元數(shù)據(jù)
10.7 讀取目錄內(nèi)容
10.8 共享文件
- 描述符表
- 文件表
- v-node表
10.9 I/O重定向
10.10 標(biāo)準(zhǔn)I/O
10.11 綜合:我該使用哪些I/O函數(shù)?
10.12 小結(jié)
第十一章 網(wǎng)絡(luò)編程
11.1 客戶端-服務(wù)端編程模型
11.2 網(wǎng)絡(luò)
11.3 全球IP因特網(wǎng)
11.3.1 IP地址
11.3.2 因特網(wǎng)域名
11.3.3 因特網(wǎng)連接
11.4 套接字接口
11.4.1 套接字地址結(jié)構(gòu)
11.4.2 socket函數(shù)
11.4.3 connect函數(shù)
11.4.4 bind函數(shù)
11.4.5 listen函數(shù)
11.4.6 accept函數(shù)
11.4.7 主機(jī)和服務(wù)的轉(zhuǎn)換
- getaddrinfo函數(shù)
- getnameinfo函數(shù)
11.4.8 套接字接口的輔助函數(shù)
- open_clientfd函數(shù)
- open_listenfd函數(shù)
11.4.9 echo客戶端和服務(wù)端的示例
11.5 Web服務(wù)器
11.5.1 Web基礎(chǔ)
11.5.2 Web內(nèi)容
11.5.3 HTTP事務(wù)
1.HTTP請求
2.HTTP響應(yīng)
11.5.4 服務(wù)動(dòng)態(tài)內(nèi)容
- 客戶端如何將程序參數(shù)傳遞個(gè)服務(wù)器
- 服務(wù)端如何將參數(shù)傳遞給子進(jìn)程
- 服務(wù)器如何將其他信息傳遞給子進(jìn)程
- 子進(jìn)程將它的輸出發(fā)送到哪里
11.6 綜合:TINY Web服務(wù)器
11.7 小結(jié)
第十二章 并發(fā)編程
12.1 基于進(jìn)程的并發(fā)編程
12.1.1 基于進(jìn)程的并發(fā)服務(wù)器
12.1.2 進(jìn)程的優(yōu)劣
12.2 基于I/O多路復(fù)用的并發(fā)編程
12.2.1 基于I/O多路復(fù)用的并發(fā)事件驅(qū)動(dòng)服務(wù)器
12.2.2 基于I/O多路復(fù)用的優(yōu)劣
優(yōu)點(diǎn)1. 它比基于進(jìn)程的設(shè)計(jì)給了程序員更多的對程序行為的控制
優(yōu)點(diǎn)2. 一個(gè)基于I/O多路復(fù)用的事件驅(qū)動(dòng)服務(wù)器是運(yùn)行在單一進(jìn)程上下文中的谦疾,因此每個(gè)邏輯流都能訪問該進(jìn)程的全部地址控件。這使得在流之間共享數(shù)據(jù)變得很容易鳍侣。
優(yōu)點(diǎn)3. 事件驅(qū)動(dòng)設(shè)計(jì)常常比基于進(jìn)程的設(shè)計(jì)要高效得多,因?yàn)樗鼈儾恍枰M(jìn)程上下文切換來調(diào)度新的流。
缺點(diǎn):編碼復(fù)雜萎庭,隨著并發(fā)粒度的減小,復(fù)雜性還會(huì)上升齿拂。
12.3 基于線程的并發(fā)編程
12.3.1 線程執(zhí)行模型
12.3.2 Posix線程
12.3.3 創(chuàng)建線程
12.3.4 終止線程
- 當(dāng)頂層的線程例程返回時(shí)驳规,線程會(huì)隱式地終止
- 通過調(diào)用pthread_exit函數(shù),線程會(huì)顯式地終止署海。
- 某個(gè)對等線程調(diào)用Linux的exit函數(shù)吗购,該函數(shù)終止進(jìn)程以及所有與該進(jìn)程相關(guān)的線程医男。
- 另一個(gè)對等線程通過以當(dāng)前 線程ID作為參數(shù)調(diào)用pthread_cancel函數(shù)來終止當(dāng)前線程。
12.3.5 回收已終止線程的資源
12.3.6 分離線程
12.3.7 初始化線程
12.3.8 基于線程的并發(fā)服務(wù)器
12.4 多線程程序中的共享變量
12.4.1 線程內(nèi)存模型
12.4.2 將變量映射到內(nèi)存
- 全局變量
- 本地自動(dòng)變量
- 本地靜態(tài)變量
12.4.3 共享變量
12.5 用信號量同步線程
12.5.1 進(jìn)度圖
12.5.2 信號量
12.5.3 使用信號量來實(shí)現(xiàn)互斥
12.5.4 利用信號量來調(diào)度共享資源
- 生產(chǎn)者-消費(fèi)者的問題
- 讀者-寫者問題
12.5.5 綜合:基于預(yù)線程化的并發(fā)服務(wù)器
12.6 使用線程提高并發(fā)性
12.7 其他并發(fā)問題
12.7.1 線程安全
四個(gè)線程不安全函數(shù)類
- 不保護(hù)共享變量的函數(shù)捻勉。
- 保持跨越多個(gè)調(diào)用的狀態(tài)的函數(shù)镀梭。
- 返回指向靜態(tài)變量的指針的函數(shù)。
- 調(diào)用線程不安全函數(shù)的函數(shù)踱启。
12.7.2 可重入性
12.7.3 在線程化的程序中使用已存在的庫函數(shù)
12.7.4 競爭
12.7.5 死鎖
信號量引入了一種潛在的令人厭惡的運(yùn)行時(shí)錯(cuò)誤报账,叫做死鎖。它指的是一組線程被阻塞了禽捆,等待一個(gè)永遠(yuǎn)也不會(huì)為真的條件笙什。