嵌入式 Linux 與物聯網軟件開發 : C語言內核深度解析 嵌入式Linux与物联网软件开发:C语言内核深度解析

朱有鵬, 張先鳳

買這商品的人也買了...

商品描述

<內容簡介>

本書的原型思想和內容,發源於朱有鵬老師早些年的研發和學習經歷,發展於後來數年的線下培訓授課經歷,並成熟於視頻課程《C語言高級專題》(隸屬於《朱有鵬老師嵌入式Linux核心課程》系列視頻課程的第4部分)。本書正是基於這套視頻課程的課件整理而來,參與各章節整理和編寫的都是學習了視頻課程的學生,由朱有鵬老師和張先鳳老師檢驗並完善成書。這些參與編寫的同學有的已經工作數年、有的則尚未走出大學校園。選擇他們合作創作本書,就是為了告訴讀者:做技術並不要求你天賦異稟,只需要你感興趣、願意去探索和練習,你也可以成功。

<章節目錄>


1.1引言
1.2計算機程序運行的目的
1.2.1什麼是程序
1.2.2計算機運行程序的目的
1.2.3靜態內存SRAM和動態內存DRAM
1.2.4馮·諾伊曼結構和哈佛結構
1.2.5總結:程序運行為什麼需要內存呢
1.2.6深入思考:如何管理內存(無OS時,有OS時)
1.3位、字節、半字、字的概念和內存位寬
1.3.1深入瞭解內存(硬件和邏輯兩個角度)
1.3.2內存的邏輯抽像圖(內存的編程模型)
1.3.3位和字節
1.3.4字和半字
1.3.5內存位寬(硬件和邏輯兩個角度)
1.4內存編址和尋址、內存對齊
1.4.1內存編址方法
1.4.2關鍵:內存編址是以字節為單位
1.4.3內存和數據類型的關係
1.4.4內存對齊
1.5 C語言如何操作內存
1.5.1 C語言對內存地址的封裝
1.5.2用指針來間接訪問內存
1.5.3指針類型的含義
1.5.4用數組來管理內存
1.6內存管理之結構體
1.6.1數據結構這門學問的意義
1.6.2最簡單的數據結構:數組
1.6.3數組的優缺點
1.6.4結構體隆重登場
1.6.5題外話:結構體內嵌指針實現面向對象
1.7內存管理之棧(stack)
1.7 .1什麼是棧
1.7.2棧管理內存的特點(小內存、自動化)
1.7.3棧的應用舉例:局部變量和函數調用
1.7.4棧的約束(預定棧大小不靈活,怕溢出)
1.8內存管理之堆
1.8.1什麼是堆
1.8.2堆管理內存的特點(大塊內存、手工分配/使用/釋放)
1.8.3 C語言操作堆內存的接口(malloc/free)
1.8.4堆的優勢和劣勢(管理大塊內存、靈活、容易內存洩漏)
1.8.5靜態存儲區
課後題
第2章C語言位操作
2.1引言
2.2常用位操作符
2.2.1位與(&)
2.2.2位或(|)
2.2.3位取反(~)
2.2.4位異或(;)
2.2.5左移位(<<)
2.2.6右移位(>>)
2.3位操作與寄存器
2.3.1寄存器的操作
2.3.2寄存器特定位清零用&
2.3.3寄存器特定位置1用|
2.3.4寄存器特定位取反用~
2.4位運算構建特定二進制數
2.4.1使用移位獲取特定位為1的二進制數
2.4.2結合位取反獲取特定位為0的二進制數
2.4.3總結
2.5位運算實戰演練1
2.5.1給定整型數a,設置a的bit3,保證其他位不變
2.5.2給定整型數a,設置a的bit3~bit7,保持其他位不變
2.5.3給定整型數a,清除a的bit15,保證其他位不變
2.5.4給定整型數a,清除a的bit15~bit23,保持其他位不變
2.5.5給定整型數a,取出a的bit3~bit8
2.5.6用C語言給寄存器a的bit7~bit17賦值937(其餘位不受影響)
2.6位運算實戰演練2
2.6.1用C語言將寄存器a的bit7~bit17中的值加17(其餘位不受影響)
2.6.2用C語言給寄存器a的bit7~bit17賦值937,同時給bit21~bit25賦值17
2.7技術升級:用宏定義來完成位運算
2.7.1直接用宏來置位
2.7.2直接用宏來復位
2.7.3截取變量的部分連續位
課後題
第3章指針才是C語言的精髓
3.1引言
3.2指針到底是什麼
3.2.1普通變量
3.2.2指針變量
3.2.3變量空間的首字節地址,作為整個空間的地址
3.2.4指針變量的類型作用
3.2.5為什麼需要指針
3.2 .6高級語言如Java、C#的指針到哪裡去了
3.2.7指針使用之三部曲
3.3理解指針符號
3.3.1星號*的理解
3.3.2取地址符&的理解
3.3.3指針變量的初始化和指針變量賦值之間的區別
3.3.4左值與右值
3.3.5定義指針後,需要關心的一些內容
3.4野指針與段錯誤問題
3.4.1什麼是野指針
3.4.2野指針可能引發的危害
3.4.3野指針產生的原因
3.4.4如何避免野指針
3.4.5 NULL到底是什麼
3.4.6段錯誤產生的原因匯總
3.5 const關鍵字與指針
3.5.1什麼是const
3.5.2 const對於普通變量的修飾
3.5.3const修飾指針的三種形式
3.5.4 const的變量真的不能改嗎
3.5.5為什麼要用const
3.5.6有關變量和常量的探討
3.6深入學習數組
3.6.1為什麼需要數組
3.6.2從編譯器角度理解數組
3.6.3從內存角度理解數組
3.6.4一位數組中幾個關鍵符號的理解
3.7指針與數組的天生“姻緣”
3.7.1如何使用指針訪問數組
3.7.2從內存角度理解指針訪問數組的實質
3.7.3指針與數組類型的匹配問題
3.7.4總結:指針類型決定了指針如何參與運算
3.8指針類型與強制類型轉換
3.8.1變量數據類型的作用
3.8.2數據的存入和讀取
3.8.3普通變量的強制轉換
3.8.4指針變量數據類型的含義
3.8.5指針變量數據類型的強制轉換
3.9指針、數組與sizeof運算符
3.9.1 charstr()=" hello";sizeof(str),sizeof(str(0)),strlen(str)
3.9.2 charstr()="hello";char*p=str;sizeof(*p)
3.9.3 intb(100); sizeof(b)
3.9.4數組的傳參
3.9.5 #define和typedef的區別
3.10指針與函數傳參
3.10.1普通傳參
3.10.2傳遞地址(指針)
3.10.3傳遞數組
3.10.4傳遞結構體
3.10.5傳遞普通值和傳遞地址的異同,以及傳遞地址(指針)應該遵循的原則
3.11輸入型參數與輸出型參數
3.11.1函數為什麼需要傳參和返回值
3.11.2函數傳參中為什麼使用const指針
3.11.3總結
課後題
第4章C語言複雜表達式與指針高級應用
4.1引言
4.2指針數組與數組指針
4.2.1簡單理解指針數組與數組指針
4.2.2分析指針數組與數組指針的表達式
4.3函數指針與typedef
4.3.1函數指針的實質(還是指針變量)
4.3.2函數指針的書寫和分析方法
4.3.3 typedef關鍵字的用法
4.4函數指針實戰1—用函數指針調用執行函數
4.5函數指針實戰2—結構體內嵌函數指針實現分層
4.6再論typedef
4.6.1輕鬆理解和應用typedef
4.6.2 typedef與#define宏的區別
4.6.3 typedef與struct
4.6.4 typedef與const
4.6. 5使用typedef的重要意義
4.6.6二重指針
4.7二維數組
4.7.1二維數組的內存映像
4.7.2識別第一維和第二維
4.7.3數組名代表數組首元素的地址
4.7.4指針訪問二維數組的兩種方式
4.7.5總結
課後題
第5章數組&字符串&結構體&共享體&枚舉
5.1引言
5.2程序中的內存從哪裡來
5.2.1三種內存來源:棧(stack)、堆(heap)、數據區(.data)
5.2.2棧內存特點詳解
5.3堆
5.3.1堆內存特點詳解
5.3.2使用堆內存註意事項
5.3.3 malloc的一些細節表現
5.4內存中的各個段
5.4.1代碼段、數據段、bss段
5.4.2特殊數據會被放到代碼段
5.4.3未初始化或顯式初始化為0的全局變量放在bss段
5.4.4內存管理方式的總結
5.5 C語言的字符串類型
5.5.1 C語言使用指針來管理字符串
5.5.2 C語言中字符串的本質:指向字符串的存放空間的指針
5.5.3指向字符串的指針變量空間和字符串存放的空間是分開的
5.5.4存儲多個字符的兩種方式—字符串和字符數組
5.6字符串和字符數組的細節
5.6.1字符數組的初始化、sizeof以及strlen
5.6.2字符串的初始化與sizeof、strlen
5.6.3字符數組與字符串的本質差異
5.7結構體概述
5.7.1結構體使用時先定義結構體類型,再用類型定義變量
5.7.2從數組到結構體的進步之處
5.7 .3結構體變量中的元素如何訪問
5.8結構體的對齊訪問
5.8.1結構體對齊訪問實例
5.8.2結構體為何要對齊訪問
5.8.3結構體對齊的規則和運算
5.8.4手動對齊
5.8. 5 GCC推薦的對齊指令:_attribute_((packed))和_attribute_((aligned(n)))
5.9 offsetof宏與container_of宏
5.9.1由結構體指針進而訪問各元素的原理
5.9.2 offsetof宏
5.9. 3 container_of宏
5.9.4學習指南和要求
5.10共享體(union)
5.10.1共享體的類型聲明、變量定義和使用
5.10.2共享體和結構體的區別
5.10.3共享體的主要用途
5.11大小端模式
5.11.1什麼是大小端模式
5.11.2用union來測試機器的大小端模式
5.11.3用指針方式來測試機器的大小端
5.11.4通信系統中的大小端(數組的大小端)
5.12枚舉enum
5.12.1枚舉的作用是什麼
5.12.2 C語言為何需要枚舉
5.12.3宏定義和枚舉的區別
5.12.4枚舉的定義形式
課後題
第6章C語言的預處理、函數和函數庫
6.1引言
6.2 C語言為什麼需要編譯鏈接
6.2.1編譯鏈接的流程
6.2.2編譯鏈接中各種文件擴展名的含義
6.3預處理詳解
6.3.1 C語言預處理的意義
6.3.2預處理涉及的內容
6.3.3使用GCC進行編譯和鏈接的過程
6.4常見的預處理詳解
6.4.1文件包含
6.4.2註釋
6.4.3宏定義
6.4.4條件編譯
6.5函數的本質
6.5.1 C語言為什麼會有函數
6.5.2函數書寫的一般原則
6.5.3函數是動詞、變量是名詞(面向對像中分別叫方法和成員變量)
6.5.4函數的實質是數據處理器
6.6函數的基本使用
6.6.1函數三要素:定義、聲明、調用
6.6.2函數原型和作用
6.7遞歸函數
6.7.1函數的調用機制
6.7.2遞歸函數
6.7.3使用遞歸的原則:收斂性、棧溢出
6.7.4遞歸與循環的區別
6.8庫函數
6.8.1什麼是函數庫
6.8.2函數庫的由來
6.8.3函數庫的提供形式:靜態鏈接庫與動態鏈接庫
6.8.4庫函數的使用
6.9常見的庫函數之字符串函數
6.9.1什麼是字符串
6.9.2字符串處理函數
6.9.3 man手冊的引入
6.9.4 man手冊的使用
6.9.5常用的字符串處理函數
6.10常見的庫函數之數學庫函數
6.10. 1數學庫函數
6.10.2計算開平方
6.10.3鏈接時加—lm
6.11製作靜態鏈接庫並使用
6.12製作動態鏈接庫並使用
課後題
第7章存儲類&作用域&生命週期&鏈接屬性
7.1引言
7.2概念解析
7.2.1存儲類
7.2.2作用域
7.2.3生命週期
7.2.4鏈接屬性
7.3 Linux下C程序的內存映像
7.3.1代碼段、rodata段(只讀數據段)
7.3.2數據段、bss段
7.3.3堆
7.3.4文件映射區
7.3.5棧
7.3.6內核映射區
7.3.7操作系統下和裸機下C程序加載執行的差異
7.4存儲類相關的關鍵字1
7.4.1 auto
7.4.2 static
7.4.3 register
7.5存儲類相關的關鍵字2
7.5.1 extern
7.5.2 volatile
7.5.3 restrict
7.5.4 typedef
7.6作用域詳解
7.6.1局部變量的代碼塊作用域
7.6.2函數名和全局變量的文件作用域
7.7變量的生命週期
7.7.1研究變量生命週期的意義
7.7.2棧變量的生命週期
7.7.3堆變量的生命週期
7.7.4數據段、bss段變量的生命週期
7.7.5代碼段、只讀段的生命週期
7.8鏈接屬性
7.8.1 C語言程序的組織架構:多個C文件+多個h文件
7.8.2編譯以文件為單位、鏈接以工程為單位
7.8. 3三種鏈接屬性:外連接、內鏈接、無鏈接
7.8.4函數和全局變量的命名衝突問題
7.8.5 static的第二種用法:修飾全局變量和函數
課後題
第8章C語言關鍵細節討論
8.1引言
8.2操作系統概述
8.2.1什麼是操作系統
8.2.2 C庫函數
8.2.3操作系統的重大意義
8.3 main函數返回值
8.3.1普通函數的返回值
8.3.2 main函數的返回值
8.3 .3誰調用了main函數
8.4 argc、argv與main函數的傳參
8.5 void類型的本質
8.6 C語言中的NULL
8.6.1 NULL的定義
8.6.2 '\0'、'0'、0和NULL的區別
8.7運算中的臨時匿名變量
8.7.1 C語言和彙編語言的區別
8.7.2強制類型轉換
8.7.3使用臨時變量來理解不同數據類型之間的運算
8.8順序結構
8.8.1 C語言中的結構
8.8.2編譯過程中的順序結構
8.8.3思考:為什麼本質都是順序結構
8.9程序調試
8.9.1程序調試手段
8.9.2調試(DEBUG)版本和發行(RELEASE)版本的區別
8.9.3 debug宏的使用方法
課後題
第9章鍊錶&狀態機&多線程
9.1引言
9.2鍊錶的引入
9.2.1數組的缺陷
9.2.2鍊錶是什麼樣子的
9.2.3鍊錶的作用是什麼
9.3單鍊錶的實現之構建第一個節點
9.3.1不實用卻意義重大的簡單鍊錶
9.3.2從簡單的鍊錶開始
9.3.3單鍊錶的節點構成
9.3.4使用堆內存創建一個節點
9.3.5鍊錶的頭指針
9.3. 6構建第一個簡單的鍊錶
9.4單鍊錶的實現之從尾部插入節點
9.4.1從尾部插入節點
9.4.2構建第一個簡單的鍊錶
9.4.3什麼是頭節點
9.5單鍊錶的算法之從頭部插入節點
9.5.1鍊錶頭部插入思路解析
9.5.2箭頭非指向
9.6單鍊錶的算法之遍歷節點
9.6.1什麼是遍歷
9.6.2如何遍歷單鍊錶
9.6.3代碼分析
9.7單鍊錶的算法之刪除節點
9.7.1為什麼要刪除節點
9.7.2註意堆內存的釋放
9.7.3設計一個刪除節點算法
9.8單鍊錶的算法之逆序
9.8.1什麼是鍊錶的逆序
9.8.2單鍊錶的逆序算法分析
9.8 .3編程實現逆序算法
9.8.4數據結構與算法的關係
9.9雙鍊錶的引入和基本實現
9.9.1單鍊錶的優缺點
9.9.2雙鍊錶的結構
9.10雙鍊錶的算法之插入節點
9.10.1尾部插入
9.10.2頭部插入
9.11雙鍊錶的算法之遍歷
9.11.1正向遍歷
9.11.2逆向遍歷
9.12雙鍊錶的算法之刪除節點
9.13 Linux內核鍊錶
9.13.1前述鍊錶數據區域的局限性
9.13.2解決思路:數據區的結構體的封裝由用戶實現,通用部分通過調用函數實現
9.13.3內核鍊錶的設計思路
9.13.4 list.h文件簡介
9.14內核鍊錶的基本算法和使用簡介
9.14.1內核鍊錶的常用操作
9.14.2內核鍊錶的使用實踐
9.15什麼是狀態機
9.15.1有限狀態機
9.15.2兩種狀態機:Moore型和Mealy型
9.15.3狀態機的主要用途
9.15.4狀態機解決了什麼問題
9.16用C語言實現簡單的狀態機
9.16.1題目:開鎖狀態機
9.16.2題目分析
9.17多線程簡介
9.17.1操作系統下的並行執行機制
9.17.2進程和線程的區別和聯繫
9.17. 3多線程的優勢
課後題
第10章程序員和編譯器的曖昧
10.1引言
10.2編程工作的演進史
10.2.1 CPU與二進制
10.2.2編程語言的革命
10.3程序員、編譯器和CPU之間的三角戀
10.3.1程序員與CPU的之間的“翻譯”—編譯器
10.3.2高級語言與低級語言的差別
10.4像編譯器一樣思考吧—理論篇
10.4.1編譯器的結構
10.4.2語法是什麼?語法就是編譯器的習性
10.5像編譯器一樣思考吧—實戰篇
10.5.1充分地利用語法規則,寫出簡潔、高效的代碼
10.5.2複雜表達式理解
課後題
附錄答案
第1章課後題答案
第2章課後題答案
第3章課後題答案
第4章課後題答案
第5章課後題答案
第6章課後題答案
第7章課後題答案
第8章課後題答案
第9章課後題答案
第10章課後題答案