嵌入式C語言自我修養(yǎng)——從芯片、編譯器到操作系統(tǒng)
鏈接:https://pan.baidu.com/s/1dgR6wpBWD6ex4UVa5RZUxg?pwd=g1ne?
提取碼:g1ne

編輯推薦
適讀人群 :嵌入式學(xué)習(xí)者、開發(fā)者,從事Linux下C語言開發(fā)工作的人員
★ 多年嵌入式開發(fā)及培訓(xùn)一線實戰(zhàn)經(jīng)驗傾囊分享
★ 內(nèi)容幾乎涵蓋了嵌入式開發(fā)的所有知識點
★ 從底層到上層,從芯片、硬件到軟件、框架
★ 大白話寫作風(fēng)格,通俗易懂,不怕學(xué)不會
★ 在ARM平臺下講解程序的編譯、鏈接和運行原理
★ 現(xiàn)場“手撕”ARM匯編代碼,剖析C函數(shù)調(diào)用、傳參過程
★ 多角度剖析C:CPU/計算機體系結(jié)構(gòu)/編譯器/操作系統(tǒng)/軟件工程
★ GNU C編譯器擴展語法精講(在GNU開源軟件、Linux內(nèi)核中)
★ 內(nèi)存堆棧管理機制的底層剖析,從根源上理解內(nèi)存錯誤
★ 從零開始一步一步搭建和迭代嵌入式軟件框架
★ 教你用OOP思想分析Linux內(nèi)核中復(fù)雜的驅(qū)動和子系統(tǒng)
★ C語言的多任務(wù)并發(fā)編程思想,CPU和操作系統(tǒng)零基礎(chǔ)入門
★ 幫你快速構(gòu)建嵌入式完整知識體系
★ 擴充AIoT時代嵌入式新的知識點
★ 更難能可貴的是,本書內(nèi)容經(jīng)過大量學(xué)員的驗證
★ 學(xué)員說好才是真的好
內(nèi)容簡介
《嵌入式C語言自我修養(yǎng):從芯片、編譯器到操作系統(tǒng)》是一本專門為嵌入式讀者打造的C語言進階學(xué)習(xí)圖書。本書的學(xué)習(xí)重點不再是C語言的基本語法,而是和嵌入式、C語言相關(guān)的一系列知識。作者以C語言為切入點,分別探討了嵌入式開發(fā)所需要的諸多核心理論和技能,力圖幫助讀者從零搭建嵌入式開發(fā)所需要的完整知識體系和技能樹。
《嵌入式C語言自我修養(yǎng):從芯片、編譯器到操作系統(tǒng)》從底層CPU的制造流程和工作原理開始講起,到計算機體系結(jié)構(gòu),C程序的反匯編分析,程序的編譯、運行和重定位,程序運行時的堆棧內(nèi)存動態(tài)變化,GNU C編譯器的擴展語法,指針的靈活使用,C語言的面向?qū)ο缶幊趟枷?,C語言的模塊化編程思想,C語言的多任務(wù)編程思想,進程、線程和協(xié)程的概念,從底層到上層,從芯片、硬件到軟件、框架,幾乎涵蓋了嵌入式開發(fā)的所有知識點。
本書適合嵌入式學(xué)習(xí)者、開發(fā)者閱讀學(xué)習(xí),同樣適合從事Linux下C語言開發(fā)工作的人員作為參考。閱讀本書需要讀者有一定的C語言基礎(chǔ),無論你是在校學(xué)生,還是需要充電學(xué)習(xí)的工程師,掌握了C語言的基本語法和編程技能后再閱讀本書,學(xué)習(xí)效果會更佳。
作者簡介
王利濤
嵌入式工程師,培訓(xùn)講師,多年嵌入式開發(fā)經(jīng)驗,包括芯片測試、BSP、驅(qū)動開發(fā)、USB子系統(tǒng)等,目前在開發(fā)“嵌入式工程師自我修養(yǎng)”系列在線視頻教程,以及在個人博客“宅學(xué)部落”分享更多的嵌入式、Linux、AIoT技術(shù)。
精彩書評
銀行家張:王老師的課很好,有深度又講解到位,相對容易理解。
活寶大太陽:深入淺出,細致、深入,看完后很痛快的感覺!
匿名:很好,透徹!
不知路漫漫:很酷的講解,感覺很通透,干貨滿滿,期待更多的精彩!
猜中007:講得很棒,正是俺需要的!
nbyuxia:講得很仔細,經(jīng)驗豐富,把以前不知道的知識都給補上了,非常棒!
isakura:王老師很厲害,我自學(xué)了他的C語言課程,大呼過癮啊!我買了他的所有課程,希望跟著王老師把C語言學(xué)精通起來!
軒轅_魏:講得不錯,斷斷續(xù)續(xù)地看完了,準(zhǔn)備入手第二部!
tzlmm:解釋了很多疑惑、之前的謎團,真的很幸運,能夠看到這么好的講解,可以少走很多彎路,弄清楚很多概念。
panhuzhuan2:講得很好,特別是對有一些工程經(jīng)驗的人來說,看得出老師是花了心思的。
qq_1655190x:嵌入式“良心”課程,都是干貨!
fengzheng445:好評,講得很深入!
……
目錄
第1章工欲善其事,必先利其器
1.1 代碼編輯工具:Vim
1.1.1 安裝Vim
1.1.2 Vim常用命令
1.1.3 Vim配置文件:vimrc
1.1.4 Vim的按鍵映射
1.2 程序編譯工具:make
1.2.1 使用IDE編譯C程序
1.2.2 使用gcc編譯C源程序
1.2.3 使用make編譯程序
1.3 代碼管理工具:Git
1.3.1 什么是版本控制系統(tǒng)
1.3.2 Git的安裝和配置
1.3.3 Git常用命令
第2章計算機體系結(jié)構(gòu)與CPU工作原理
2.1 一顆芯片是怎樣誕生的
2.1.1 從沙子到單晶硅
2.1.2 PN結(jié)的工作原理
2.1.3 從PN結(jié)到芯片電路
2.1.4 芯片的封裝
2.2 一顆CPU是怎么設(shè)計出來的
2.2.1 計算機理論基石:圖靈機
2.2.2 CPU內(nèi)部結(jié)構(gòu)及工作原理
2.2.3 CPU設(shè)計流程
2.3 計算機體系結(jié)構(gòu)
2.3.1 馮·諾依曼架構(gòu)
2.3.2 哈弗架構(gòu)
2.3.3 混合架構(gòu)
2.4 CPU性能提升:Cache機制
2.4.1 Cache的工作原理
2.4.2 一級Cache和二級Cache
2.4.3 為什么有些處理器沒有Cache
2.5 CPU性能提升:流水線
2.5.1 流水線工作原理
2.5.2 超流水線技術(shù)
2.5.3 流水線冒險
2.5.4 分支預(yù)測
2.5.5 亂序執(zhí)行
2.5.6 SIMD和NEON
2.5.7 單發(fā)射和多發(fā)射
2.6 多核CPU
2.6.1 單核處理器的瓶頸
2.6.2 片上多核互連技術(shù)
2.6.3 big.LITTLE結(jié)構(gòu)
2.6.4 超線程技術(shù)
2.6.5 CPU核數(shù)越多越好嗎
2.7 后摩爾時代:異構(gòu)計算的崛起
2.7.1 什么是異構(gòu)計算
2.7.2 GPU
2.7.3 DSP
2.7.4 FPGA
2.7.5 TPU
2.7.6 NPU
2.7.7 后摩爾時代的XPU們
2.8 總線與地址
2.8.1 地址的本質(zhì)
2.8.2 總線的概念
2.8.3 總線編址方式
2.9 指令集與微架構(gòu)
2.9.1 什么是指令集
2.9.2 什么是微架構(gòu)
2.9.3 指令助記符:匯編語言
第3章ARM體系結(jié)構(gòu)與匯編語言
3.1 ARM體系結(jié)構(gòu)
3.2 ARM匯編指令
3.2.1 存儲訪問指令
3.2.2 數(shù)據(jù)傳送指令
3.2.3 算術(shù)邏輯運算指令
3.2.4 操作數(shù):operand2詳解
3.2.5 比較指令
3.2.6 條件執(zhí)行指令
3.2.7 跳轉(zhuǎn)指令
3.3 ARM尋址方式
3.3.1 寄存器尋址
3.3.2 立即數(shù)尋址
3.3.3 寄存器偏移尋址
3.3.4 寄存器間接尋址
3.3.5 基址尋址
3.3.6 多寄存器尋址
3.3.7 相對尋址
3.4 ARM偽指令
3.4.1 LDR偽指令
3.4.2 ADR偽指令
3.5 ARM匯編程序設(shè)計
3.5.1 ARM匯編程序格式
3.5.2 符號與標(biāo)號
3.5.3 偽操作
3.6 C語言和匯編語言混合編程
3.6.1 ATPCS規(guī)則
3.6.2 在C程序中內(nèi)嵌匯編代碼
3.6.3 在匯編程序中調(diào)用C程序
3.7 GNU ARM匯編語言
3.7.1 重新認識編譯器
3.7.2 GNU ARM編譯器的偽操作
3.7.3 GNU ARM匯編語言中的標(biāo)號
3.7.4 .section偽操作
3.7.5 基本數(shù)據(jù)格式
3.7.6 數(shù)據(jù)定義
3.7.7 匯編代碼分析實戰(zhàn)
第4章程序的編譯、鏈接、安裝和運行
4.1 從源程序到二進制文件
4.2 預(yù)處理過程
4.3 程序的編譯
4.3.1 從C文件到匯編文件
4.3.2 匯編過程
4.3.3 符號表與重定位表
4.4 鏈接過程
4.4.1 分段組裝
4.4.2 符號決議
4.4.3 重定位
4.5 程序的安裝
4.5.1 程序安裝的本質(zhì)
4.5.2 在Linux下制作軟件安裝包
4.5.3 使用apt-get在線安裝軟件
4.5.4 在Windows下制作軟件安裝包
4.6 程序的運行
4.6.1 操作系統(tǒng)環(huán)境下的程序運行
4.6.2 裸機環(huán)境下的程序運行
4.6.3 程序入口main()函數(shù)分析
4.6.4 BSS段的小秘密
4.7 鏈接靜態(tài)庫
4.8 動態(tài)鏈接
4.8.1 與地址無關(guān)的代碼
4.8.2 全局偏移表
4.8.3 延遲綁定
4.8.4 共享庫
4.9 插件的工作原理
4.10 Linux內(nèi)核模塊運行機制
4.11 Linux內(nèi)核編譯和啟動分析
4.12 U-boot重定位分析
4.13 常用的binutils工具集
第5章內(nèi)存堆棧管理
5.1 程序運行的“馬甲”:進程
5.2 Linux環(huán)境下的內(nèi)存管理
5.3 棧的管理
5.3.1 棧的初始化
5.3.2 函數(shù)調(diào)用
5.3.3 參數(shù)傳遞
5.3.4 形參與實參
5.3.5 棧與作用域
5.3.6 棧溢出攻擊原理
5.4 堆內(nèi)存管理
5.4.1 裸機環(huán)境下的堆內(nèi)存管理
5.4.2 uC/OS的堆內(nèi)存管理
5.4.3 Linux堆內(nèi)存管理
5.4.4 堆內(nèi)存測試程序
5.4.5 實現(xiàn)自己的堆管理器
5.5 mmap映射區(qū)域探秘
5.5.1 將文件映射到內(nèi)存
5.5.2 mmap映射實現(xiàn)機制分析
5.5.3 把設(shè)備映射到內(nèi)存
5.5.4 多進程共享動態(tài)庫
5.6 內(nèi)存泄漏與防范
5.6.1 一個內(nèi)存泄漏的例子
5.6.2 預(yù)防內(nèi)存泄漏
5.6.3 內(nèi)存泄漏檢測:MTrace
5.6.4 廣義上的內(nèi)存泄漏
5.7 常見的內(nèi)存錯誤及檢測
5.7.1 總有一個Bug,讓你淚流滿面
5.7.2 使用core dump調(diào)試段錯誤
5.7.3 什么是內(nèi)存踩踏
5.7.4 內(nèi)存踩踏監(jiān)測:mprotect
5.7.5 內(nèi)存檢測神器:Valgrind
第6章GNU C編譯器擴展語法精講
6.1 C語言標(biāo)準(zhǔn)和編譯器
6.1.1 什么是C語言標(biāo)準(zhǔn)
6.1.2 C語言標(biāo)準(zhǔn)的內(nèi)容
6.1.3 C語言標(biāo)準(zhǔn)的發(fā)展過程
6.1.4 編譯器對C語言標(biāo)準(zhǔn)的支持
6.1.5 編譯器對C語言標(biāo)準(zhǔn)的擴展
6.2 指定初始化
6.2.1 指定初始化數(shù)組元素
6.2.2 指定初始化結(jié)構(gòu)體成員
6.2.3 Linux內(nèi)核驅(qū)動注冊
6.2.4 指定初始化的好處
6.3 宏構(gòu)造“利器”:語句表達式
6.3.1 表達式、語句和代碼塊
6.3.2 語句表達式
6.3.3 在宏定義中使用語句表達式
6.3.4 內(nèi)核中的語句表達式
6.4 typeof與container_of宏
6.4.1 typeof關(guān)鍵字
6.4.2 typeof使用示例
6.4.3 Linux內(nèi)核中的container_of宏
6.4.4 container_of宏實現(xiàn)分析
6.5 零長度數(shù)組
6.5.1 什么是零長度數(shù)組
6.5.2 零長度數(shù)組使用示例
6.5.3 內(nèi)核中的零長度數(shù)組
6.5.4 思考:指針與零長度數(shù)組
6.6 屬性聲明:section
6.6.1 GNU C編譯器擴展關(guān)鍵字:__attribute__
6.6.2 屬性聲明:section
6.6.3 U-boot鏡像自復(fù)制分析
6.7 屬性聲明:aligned
6.7.1 地址對齊:aligned
6.7.2 結(jié)構(gòu)體的對齊
6.7.3 思考:編譯器一定會按照aligned指定的方式對齊嗎
6.7.4 屬性聲明:packed
6.7.5 內(nèi)核中的aligned、packed聲明
6.8 屬性聲明:format
6.8.1 變參函數(shù)的格式檢查
6.8.2 變參函數(shù)的設(shè)計與實現(xiàn)
6.8.3 實現(xiàn)自己的日志打印函數(shù)
6.9 屬性聲明:weak
6.9.1 強符號和弱符號
6.9.2 函數(shù)的強符號與弱符號
6.9.3 弱符號的用途
6.9.4 屬性聲明:alias
6.10 內(nèi)聯(lián)函數(shù)
6.10.1 屬性聲明:noinline
6.10.2 什么是內(nèi)聯(lián)函數(shù)
6.10.3 內(nèi)聯(lián)函數(shù)與宏
6.10.4 編譯器對內(nèi)聯(lián)函數(shù)的處理
6.10.5 思考:內(nèi)聯(lián)函數(shù)為什么定義在頭文件中
6.11 內(nèi)建函數(shù)
6.11.1 什么是內(nèi)建函數(shù)
6.11.2 常用的內(nèi)建函數(shù)
6.11.3 C標(biāo)準(zhǔn)庫的內(nèi)建函數(shù)
6.11.4 內(nèi)建函數(shù):__builtin_constant_p(n)
6.11.5 內(nèi)建函數(shù):__builtin_expect(exp,c)
6.11.6 Linux內(nèi)核中的likely和unlikely
6.12 可變參數(shù)宏
6.12.1 什么是可變參數(shù)宏
6.12.2 繼續(xù)改進我們的宏
6.12.3 可變參數(shù)宏的另一種寫法
6.12.4 內(nèi)核中的可變參數(shù)宏
第7章數(shù)據(jù)存儲與指針
7.1 數(shù)據(jù)類型與存儲
7.1.1 大端模式與小端模式
7.1.2 有符號數(shù)和無符號數(shù)
7.1.3 數(shù)據(jù)溢出
7.1.4 數(shù)據(jù)類型轉(zhuǎn)換
7.2 數(shù)據(jù)對齊
7.2.1 為什么要數(shù)據(jù)對齊
7.2.2 結(jié)構(gòu)體對齊
7.2.3 聯(lián)合體對齊
7.3 數(shù)據(jù)的可移植性
7.4 Linux內(nèi)核中的size_t類型
7.5 為什么很多人編程時喜歡用typedef
7.5.1 typedef的基本用法
7.5.2 使用typedef的優(yōu)勢
7.5.3 使用typedef需要注意的地方
7.5.4 typedef的作用域
7.5.5 如何避免typedef被大量濫用
7.6 枚舉類型
7.6.1 使用枚舉的三種方法
7.6.2 枚舉的本質(zhì)
7.6.3 Linux內(nèi)核中的枚舉類型
7.6.4 使用枚舉需要注意的地方
7.7 常量和變量
7.7.1 變量的本質(zhì)
7.7.2 常量存儲
7.7.3 常量折疊
7.8 從變量到指針
7.8.1 指針的本質(zhì)
7.8.2 一些復(fù)雜的指針聲明
7.8.3 指針類型與運算
7.9 指針與數(shù)組的“曖昧”關(guān)系
7.9.1 下標(biāo)運算符[]
7.9.2 數(shù)組名的本質(zhì)
7.9.3 指針數(shù)組與數(shù)組指針
7.10 指針與結(jié)構(gòu)體
7.11 二級指針
7.11.1 修改指針變量的值
7.11.2 二維指針和指針數(shù)組
7.11.3 二級指針和二維數(shù)組
7.12 函數(shù)指針
7.13 重新認識void
第8章C語言的面向?qū)ο缶幊趟枷?/p>
8.1 代碼復(fù)用與分層思想
8.2 面向?qū)ο缶幊袒A(chǔ)
8.2.1 什么是OOP
8.2.2 類的封裝與實例化
8.2.3 繼承與多態(tài)
8.2.4 虛函數(shù)與純虛函數(shù)
8.3 Linux內(nèi)核中的OOP思想:封裝
8.3.1 類的C語言模擬實現(xiàn)
8.3.2 鏈表的抽象與封裝
8.3.3 設(shè)備管理模型
8.3.4 總線設(shè)備模型
8.4 Linux內(nèi)核中的OOP思想:繼承
8.4.1 繼承與私有指針
8.4.2 繼承與抽象類
8.4.3 繼承與接口
8.5 Linux內(nèi)核中的OOP思想:多態(tài)
第9章C語言的模塊化編程思想
9.1 模塊的編譯和鏈接
9.2 系統(tǒng)模塊劃分
9.2.1 模塊劃分方法
9.2.2 面向?qū)ο缶幊痰乃季S陷阱
9.2.3 規(guī)劃合理的目錄結(jié)構(gòu)
9.3 一個模塊的封裝
9.4 頭文件深度剖析
9.4.1 基本概念
9.4.2 隱式聲明
9.4.3 變量的聲明與定義
9.4.4 如何區(qū)分定義和聲明
9.4.5 前向引用和前向聲明
9.4.6 定義與聲明的一致性
9.4.7 頭文件路徑
9.4.8 Linux內(nèi)核中的頭文件
9.4.9 頭文件中的內(nèi)聯(lián)函數(shù)
9.5 模塊設(shè)計原則
9.6 被誤解的關(guān)鍵字:goto
9.7 模塊間通信
9.7.1 全局變量
9.7.2 回調(diào)函數(shù)
9.7.3 異步通信
9.8 模塊設(shè)計進階
9.8.1 跨平臺設(shè)計
9.8.2 框架
9.9 AIoT時代的模塊化編程
第10章C語言的多任務(wù)編程思想和操作系統(tǒng)入門
10.1 多任務(wù)的裸機實現(xiàn)
10.1.1 多任務(wù)的模擬實現(xiàn)
10.1.2 改變?nèi)蝿?wù)的執(zhí)行頻率
10.1.3 改變?nèi)蝿?wù)的執(zhí)行時間
10.2 操作系統(tǒng)基本原理
10.2.1 調(diào)度器工作原理
10.2.2 函數(shù)棧與進程棧
10.2.3 可重入函數(shù)
10.2.4 臨界區(qū)與臨界資源
10.3 中斷
10.3.1 中斷處理流程
10.3.2 進程棧與中斷棧
10.3.3 中斷函數(shù)的實現(xiàn)
10.4 系統(tǒng)調(diào)用
10.4.1 操作系統(tǒng)的API
10.4.2 操作系統(tǒng)的權(quán)限管理
10.4.3 CPU的特權(quán)模式
10.4.4 Linux系統(tǒng)調(diào)用接口
10.5 揭開文件系統(tǒng)的神秘面紗
10.5.1 什么是文件系統(tǒng)
10.5.2 文件系統(tǒng)的掛載
10.5.3 根文件系統(tǒng)
10.6 存儲器接口與映射
10.6.1 存儲器與接口
10.6.2 存儲映射
10.6.3 嵌入式啟動方式
10.7 內(nèi)存與外部設(shè)備
10.7.1 內(nèi)存與外存
10.7.2 外部設(shè)備
10.7.3 I/O端口與I/O內(nèi)存
10.8 寄存器操作
10.8.1 位運算應(yīng)用
10.8.2 操作寄存器
10.8.3 位域
10.9 內(nèi)存管理單元MMU
10.9.1 地址轉(zhuǎn)換
10.9.2 權(quán)限管理
10.10 進程、線程和協(xié)程
10.10.1 進程
10.10.2 線程
10.10.3 線程池
10.10.4 協(xié)程
10.10.5 小結(jié)
查看全部↓
精彩書摘
5.7.1 總有一個Bug,讓你淚流滿面
總有一種興奮讓你不能自抑,花枝亂顫;總有一個Bug讓你夙夜難眠,淚流滿面。當(dāng)一個Bug讓你毫無頭緒,讓你調(diào)到天昏地暗,到最后幾乎要放棄,開始漫無目的地亂改代碼,祈求奇跡出現(xiàn)時,說明你需要休息一下了:出去轉(zhuǎn)一轉(zhuǎn),吹個風(fēng),說不定靈感乍現(xiàn),一下子又有了思路……
發(fā)生段錯誤的根本原因在于非法訪問內(nèi)存,即訪問了權(quán)限未許可的內(nèi)存空間。在日常編程中,有哪些行為會引發(fā)段錯誤呢?
常見的錯誤行為是訪問內(nèi)存禁區(qū)。如前面的圖5-47所示的內(nèi)核空間、零地址、堆和mmap區(qū)域之間的內(nèi)存空間,這部分地址空間要么被內(nèi)核占用,要么還處于“未開發(fā)”狀態(tài),需要申請才能使用。這就和城郊的荒地一樣,你不能一看空著就跑過來蓋房子,你需要先獲得土地的使用權(quán)。
int main (void)
{
int i;
i = *(int *)0x8048000; //代碼段只能讀,不能寫
*(int *)0x8048000 = 100; //段錯誤
i = *(int *)0x0; //段錯誤
return 0;
}
當(dāng)我們往一個只讀區(qū)域的地址空間執(zhí)行寫操作時,或者訪問一個禁止訪問的地址(如零地址)時,都會發(fā)生段錯誤。在實際編程中,總會因為各種各樣的疏忽不小心觸碰到這些“紅線”,導(dǎo)致段錯誤。
#include
int main (void)
{
char *p;
*p = 1;
return 0;
}
編譯運行上面的程序,可能正常運行,也可能會發(fā)生段錯誤。在函數(shù)內(nèi)定義的局部變量如果未初始化,它的值是隨機的,如果你人品大爆發(fā),這個地址處于安全訪問區(qū),則向這個地址寫數(shù)據(jù)是沒有大問題的,至少不會報段錯誤。如果你運氣不好,這個隨機值正好處在內(nèi)核空間,你再向這個地址寫數(shù)據(jù),則程序會立刻發(fā)生段錯誤并終止運行。
在我們調(diào)試鏈表時,通常通過指針來操作每一個節(jié)點。如果指針在遍歷鏈表時已經(jīng)指向鏈表的末尾或頭部,指針已經(jīng)指向NULL了,此時再通過該指針去訪問節(jié)點的成員,就相當(dāng)于訪問零地址了,也會發(fā)生一個段錯誤,這個指針也就變成了非法指針。
在Linux環(huán)境下,每一個用戶進程默認有8MB大小的??臻g,如果你在函數(shù)內(nèi)定義大容量的數(shù)組或局部變量,就可能造成棧溢出,也會引發(fā)一個段錯誤。內(nèi)核中的線程也是如此,每一個內(nèi)核線程只有8KB的內(nèi)核棧,在實際使用中也要非常小心,防止堆棧溢出。
在訪問數(shù)組時,如果超越數(shù)組的邊界繼續(xù)訪問,也會發(fā)生一個段錯誤。我們使用malloc()申請的堆內(nèi)存,如果不小心多次使用free()進行釋放,通常也會觸發(fā)一個段錯誤。
//double_free.c
#include
int main (void)
{
char *p;
p = (char *) malloc (64);
free(p);
free(p); //引發(fā)段錯誤
return 0;
}
程序在編譯階段出現(xiàn)錯誤,我們可以通過錯誤提示信息很快定位并解決。由于C語言語法檢查的寬松性,程序中對內(nèi)存訪問的各種操作并不報錯,或者給一個警告信息,這會導(dǎo)致程序在運行期間出現(xiàn)段錯誤時很難定位。此時我們可以借助一些第三方工具來快速定位段錯誤。
查看全部↓
前言/序言
你要學(xué)習(xí)的,不僅僅是C語言……
對于上面的幾個C語言測試,如果你已經(jīng)知道了答案,并且知道其要考查的是什么知識點,恭喜你,你對C語言及計算機體系結(jié)構(gòu)的知識已經(jīng)很熟悉了。如果回答得不是很好,偷偷用百度也沒有搜到理想的答案,也不用氣餒,因為這次測試要考查的內(nèi)容其實已經(jīng)不僅僅是C語言的知識了,而是和嵌入式C語言開發(fā)相關(guān)的一些理論知識,如處理器架構(gòu)、操作系統(tǒng)、編譯原理、編譯器特性、內(nèi)存堆棧管理、Linux內(nèi)核中的GNU C擴展語法等。
當(dāng)然,上面的測試也不是為了故意扎你心或者賣關(guān)子,讓你趕緊掏腰包買下這本書,而是想要傳遞一個信息:要想從事嵌入式開發(fā)工作,尤其是嵌入式Linux內(nèi)核驅(qū)動開發(fā)工作,你要精通的不僅僅是C語言,最好還要掌握和C語言相關(guān)的一系列基礎(chǔ)理論和調(diào)試技能。筆者也是過來人,從最初學(xué)習(xí)嵌入式到從事嵌入式開發(fā)工作,這一路走來坎坷崎嶇,什么都不說了,說多了都是淚。從一開始連指針都不會用、不敢用,看內(nèi)核驅(qū)動代碼一頭霧水,越看越?jīng)]底、越看越?jīng)]自信,到現(xiàn)在不再犯怵,有自信和能力看懂內(nèi)核中的代碼細節(jié)和系統(tǒng)框架,這種進步不是天上掉下來的,也不是一不小心跌入山洞,撿到武功秘籍練出來的,而是不斷地學(xué)習(xí)和實踐、反復(fù)迭代、不斷完善自己的知識體系和技能樹,才慢慢達到的。學(xué)習(xí)沒有捷徑可走,要想真正學(xué)好嵌入式、精通嵌入式,個人覺得除了精通C語言,最好還要具備以下完整的知識體系和編程技能。
l 半導(dǎo)體基礎(chǔ)、CPU工作原理、硬件電路、計算機系統(tǒng)結(jié)構(gòu)。
l ARM體系結(jié)構(gòu)與匯編指令、匯編程序設(shè)計、ARM反匯編分析。
l 程序的編譯、鏈接、安裝、運行和重定位分析。
l 熟悉C語言標(biāo)準(zhǔn)、ARM、GNU編譯器的特性和擴展語法。
l C語言的模塊化編程思想,學(xué)會使用模塊化思想去分析復(fù)雜的系統(tǒng)。
l C語言的面向?qū)ο缶幊蹋ê喎QOOP)思想,學(xué)會使用OOP思想去分析Linux內(nèi)核驅(qū)動。
l 對指針的深刻理解,對復(fù)雜指針的聲明和靈活應(yīng)用。
l 對內(nèi)存堆棧管理、內(nèi)存泄漏、棧溢出、段錯誤的深刻理解。
l 多任務(wù)并發(fā)編程思想,CPU和操作系統(tǒng)基礎(chǔ)理論。
本書內(nèi)容及寫作初衷
本書從C語言的角度出發(fā),分10章,在默認讀者已經(jīng)掌握C語言基本語法的基礎(chǔ)上,和大家一起探討、學(xué)習(xí)C語言背后的CPU工作原理、計算機體系結(jié)構(gòu)、ARM平臺下程序的編譯/鏈接、程序運行時的內(nèi)存堆棧管理等底層知識。同時,針對嵌入式開發(fā)領(lǐng)域,用3章分別探討了C語言的面向?qū)ο缶幊趟枷?、模塊化編程思想和多任務(wù)編程思想,這些底層知識和編程思想構(gòu)成了嵌入式開發(fā)所需要的通用理論基礎(chǔ)和核心技能。尤其是對于很多從不同專業(yè)轉(zhuǎn)行到嵌入式開發(fā)的朋友,由于專業(yè)背景的差異,導(dǎo)致每個人的知識儲備和編程技能樹參差不齊,在學(xué)習(xí)嵌入式開發(fā)的過程中會經(jīng)常遇到各種各樣的問題,陷入學(xué)習(xí)的困境。
本書的寫作初衷就是為不同專業(yè)背景的讀者搭建嵌入式開發(fā)所需要的完整知識體系和認知框架。掌握了這些基礎(chǔ)理論和編程技能,也就補齊了短板,可為后續(xù)的嵌入式開發(fā)進階學(xué)習(xí)打下堅實的基礎(chǔ)。
本書特色
l 大白話寫作風(fēng)格,通俗易懂,不怕學(xué)不會,就怕你不學(xué)。
l 大量的配圖、原理圖,圖文并茂,更加有利于學(xué)習(xí)和理解。
l 在ARM平臺下講解程序的編譯、鏈接和運行原理(獨創(chuàng))。
l 現(xiàn)場“手撕”ARM匯編代碼,從反匯編角度剖析C函數(shù)調(diào)用、傳參過程。
l 多角度剖析C語言:CPU、計算機體系結(jié)構(gòu)、編譯器、操作系統(tǒng)、軟件工程。
l GNU C編譯器擴展語法精講(在GNU開源軟件、Linux內(nèi)核中大量使用)。
l 內(nèi)存堆棧管理機制的底層剖析,從根源上理解內(nèi)存錯誤。
l 從零開始一步一步搭建和迭代嵌入式軟件框架。
l 教你用OOP思想分析Linux內(nèi)核中復(fù)雜的驅(qū)動和子系統(tǒng)。
l C語言的多任務(wù)并發(fā)編程思想,CPU和操作系統(tǒng)零基礎(chǔ)入門。
讀者定位
本書針對的是嵌入式開發(fā),尤其是嵌入式Linux開發(fā)背景下的C語言進階學(xué)習(xí),比較適合在校學(xué)生、嵌入式學(xué)員、工作1~3年的職場新兵閱讀和學(xué)習(xí)。為了達到更好的學(xué)習(xí)效果,在閱讀本書之前,首先要確保你已經(jīng)掌握了C語言的基本語法,并且至少使用過一款C語言集成開發(fā)環(huán)境(VC++ 6.0、Visual Studio、C-Free、GCC都可以),開發(fā)過一個完整的C語言項目(課程設(shè)計也算)。有了這些基礎(chǔ)和編程經(jīng)驗之后,學(xué)習(xí)效果會更好。