內容簡介
《精通嵌入式Linux編程》詳細闡述了與嵌入式Linux開發相關的基本解決方案,主要包括初識嵌入式Linux開發、關於工具鏈、引導載入程式詳解、配置和構建核心、構建根檔案系統、選擇構建系統、使用Yocto進行開發、Yocto技術內幕、創建存儲策略、現場更新軟體、連線設備驅動程式、使用分線板進行原型設計、init程式、使用BusyBox runit啟動、管理電源、打包Python程式、了解進程和執行緒、管理記憶體、使用GDB進行調試、性能分析和跟蹤、實時編程等內容。此外,本書還提供了相應的示例、代碼,以幫助讀者進一步理解相關方案的實現過程。 本書適合作為高等院校計算機及相關專業的教材和教學參考書,也可作為相關開發人員的自學用書和參考手冊。
圖書目錄
目 錄
第1篇 嵌入式Linux的要素
第1章 初識嵌入式Linux開發 3
1.1 選擇Linux的原因 4
1.2 不選擇Linux的原因 5
1.3 找到合適的玩家 5
1.4 穿越項目生命周期 7
1.4.1 篇章內容概述 7
1.4.2 嵌入式Linux的4個基本要素 7
1.5 開源的意義 8
1.5.1 開源和免費有區別 8
1.5.2 開源許可機制 8
1.6 為嵌入式Linux開發選擇硬體 10
1.7 獲取本書所需硬體 11
1.7.1 Raspberry Pi 4 11
1.7.2 BeagleBone Black 12
1.7.3 QEMU 13
1.8 配置開發環境 15
1.9 小結 15
第2章 關於工具鏈 17
2.1 技術要求 17
2.2 工具鏈簡介 18
2.2.1 工具鏈的類型 20
2.2.2 CPU架構 21
2.2.3 選擇C庫 22
2.3 尋找工具鏈 24
2.4 使用crosstool-NG構建工具鏈 26
2.4.1 安裝crosstool-NG 26
2.4.2 為BeagleBone Black構建工具鏈 27
2.4.3 為QEMU構建工具鏈 28
2.5 工具鏈剖析 29
2.5.1 了解你的交叉編譯器 30
2.5.2 sysroot、庫和頭檔案 31
2.5.3 工具鏈中的其他工具 32
2.5.4 查看C庫的組件 33
2.6 與庫連結—靜態和動態連結 34
2.6.1 靜態庫 34
2.6.2 共享庫 35
2.6.3 了解共享庫版本號 36
2.7 交叉編譯的技巧 37
2.7.1 相對簡單的makefile 38
2.7.2 Autotools 38
2.7.3 編譯示例—SQLite 40
2.7.4 包配置 42
2.7.5 交叉編譯帶來的問題 43
2.7.6 CMake 44
2.8 小結 46
2.9 延伸閱讀 46
第3章 引導載入程式詳解 47
3.1 技術要求 47
3.2 引導載入程式的作用 48
3.3 引導順序 48
3.3.1 階段1—ROM代碼 49
3.3.2 階段2—SPL 51
3.3.3 階段3—TPL 52
3.4 從引導載入程式轉移到核心中 53
3.5 設備樹簡介 54
3.5.1 有關設備樹的基礎知識 54
3.5.2 reg屬性 55
3.5.3 標籤和中斷 56
3.5.4 設備樹包含檔案 57
3.5.5 編譯設備樹 59
3.6 U-Boot 60
3.6.1 構建U-Boot 60
3.6.2 安裝U-Boot 62
3.6.3 使用U-Boot 64
3.6.4 環境變數 65
3.6.5 引導鏡像格式 65
3.6.6 載入鏡像 67
3.6.7 引導Linux 69
3.6.8 使用U-Boot腳本自動化引導過程 69
3.6.9 將U-Boot移植到新板上 69
3.6.10 與特定開發板相關的檔案 71
3.6.11 配置頭檔案 73
3.6.12 構建和測試 74
3.6.13 Falcon模式 75
3.7 小結 76
第4章 配置和構建核心 77
4.1 技術要求 77
4.2 核心的作用 78
4.3 選擇核心 80
4.3.1 核心開發周期 80
4.3.2 穩定和長期支持版本 81
4.3.3 供應商支持 82
4.3.4 許可機制 82
4.4 構建核心 83
4.4.1 獲取源 83
4.4.2 了解核心配置—Kconfig 84
4.4.3 使用LOCALVERSION識別核心 88
4.4.4 使用核心模組的時機 89
4.5 編譯—Kbuild 90
4.5.1 找出要構建的核心目標 90
4.5.2 構建工件 91
4.5.3 編譯設備樹 93
4.5.4 編譯模組 93
4.5.5 清理核心源 94
4.5.6 為Raspberry Pi 4構建64位核心 94
4.5.7 為BeagleBone Black構建核心 96
4.5.8 為QEMU構建核心 97
4.6 引導核心 97
4.6.1 引導Raspberry Pi 4 97
4.6.2 引導BeagleBone Black 98
4.6.3 引導QEMU 99
4.6.4 核心恐慌 100
4.6.5 早期用戶空間 100
4.6.6 核心訊息 101
4.6.7 核心命令行 101
4.7 將Linux移植到新板上 102
4.7.1 新的設備樹 103
4.7.2 設定開發板的兼容屬性 104
4.8 小結 106
4.9 延伸閱讀 107
第5章 構建根檔案系統 109
5.1 技術要求 110
5.2 根檔案系統中應該包含的東西 110
5.3 目錄布局 111
5.3.1 暫存目錄 112
5.3.2 POSIX檔案訪問許可權 113
5.3.3 暫存目錄中的檔案所有權許可權 115
5.4 根檔案系統的程式 115
5.4.1 init程式 115
5.4.2 shell 115
5.4.3 實用程式 116
5.4.4 關於BusyBox 116
5.4.5 構建BusyBox 117
5.4.6 ToyBox—BusyBox的替代品 118
5.5 根檔案系統的庫 119
5.5.1 選擇需要的庫 119
5.5.2 通過剝離減小尺寸 120
5.6 設備節點 121
5.7 proc和sysfs檔案系統 122
5.7.1 proc和sysfs檔案系統的功能 123
5.7.2 掛載檔案系統 123
5.7.3 核心模組 124
5.8 將根檔案系統傳輸到目標 124
5.9 創建引導initramfs 125
5.9.1 獨立的initramfs 126
5.9.2 引導initramfs 126
5.9.3 使用QEMU引導 126
5.9.4 引導BeagleBone Black 127
5.9.5 掛載proc 127
5.9.6 將initramfs構建到核心鏡像中 128
5.9.7 使用設備表構建initramfs 129
5.9.8 舊的initrd格式 130
5.10 init程式 130
5.10.1 BusyBox的init程式 131
5.10.2 啟動守護進程 132
5.11 配置用戶賬戶 132
5.11.1 配置賬戶 132
5.11.2 將用戶賬戶添加到根檔案系統中 134
5.12 管理設備節點的更好方法 134
5.12.1 使用devtmpfs的示例 135
5.12.2 使用mdev的示例 135
5.12.3 靜態設備節點的優劣 136
5.13 配置網路 136
5.13.1 BusyBox中的網路配置 136
5.13.2 glibc的網路組件 137
5.14 使用設備表創建檔案系統鏡像 138
5.14.1 安裝和使用genext2fs工具 138
5.14.2 引導BeagleBone Black 139
5.15 使用NFS掛載根檔案系統 140
5.15.1 使用QEMU進行測試 141
5.15.2 使用BeagleBone Black進行測試 142
5.15.3 檔案許可權問題 142
5.16 使用TFTP載入核心 143
5.17 小結 144
5.18 延伸閱讀 144
第6章 選擇構建系統 145
6.1 技術要求 145
6.2 比較構建系統 146
6.3 分發二進制檔案 148
6.4 Buildroot簡介 148
6.4.1 Buildroot的背景知識 149
6.4.2 穩定版本和長期支持版本 149
6.4.3 安裝Buildroot 149
6.4.4 配置Buildroot 150
6.4.5 運行 151
6.4.6 以真實硬體為目標 153
6.4.7 創建自定義BSP 154
6.4.8 U-Boot配置 154
6.4.9 Linux配置 155
6.4.10 構建系統鏡像 157
6.4.11 添加自己的代碼 159
6.4.12 覆蓋層 160
6.4.13 添加包 160
6.4.14 許可合規性 162
6.5 Yocto Project簡介 162
6.5.1 Yocto Project的背景知識 163
6.5.2 穩定版本和支持 164
6.5.3 安裝Yocto Project 165
6.5.4 配置 165
6.5.5 構建 166
6.5.6 運行QEMU目標 167
6.5.7 元層 167
6.5.8 BitBake和配方 170
6.5.9 通過local.conf自定義鏡像 172
6.5.10 編寫鏡像配方 173
6.5.11 創建SDK 174
6.5.12 許可證審核 176
6.6 小結 176
6.7 延伸閱讀 177
第7章 使用Yocto進行開發 179
7.1 技術要求 179
7.2 在現有BSP之上構建鏡像 180
7.2.1 構建現有的BSP 180
7.2.2 控制Wi-Fi 186
7.2.3 控制藍牙 189
7.2.4 添加自定義層 192
7.3 使用devtool捕獲更改 195
7.3.1 開發工作流程 195
7.3.2 創建新配方 197
7.3.3 修改由配方構建的源 198
7.3.4 將配方升級到較新版本 200
7.4 構建自己的發行版 203
7.4.1 推出發行版的合適時機 203
7.4.2 創建一個新的發行層 203
7.4.3 配置發行版 204
7.4.4 向發行版添加更多配方 205
7.4.5 運行時包管理 205
7.5 配置遠程包伺服器 207
7.5.1 配置包伺服器 207
7.5.2 配置目標客戶端 208
7.6 小結 209
7.7 延伸閱讀 209
第8章 Yocto技術內幕 211
8.1 技術要求 211
8.2 Yocto架構和工作流程分解 212
8.2.1 元數據 214
8.2.2 構建任務 215
8.2.3 鏡像生成 217
8.3 將元數據分層 218
8.4 構建失敗故障排除 220
8.4.1 隔離錯誤 220
8.4.2 檢查和轉儲環境值 221
8.4.3 讀取任務日誌 222
8.4.4 添加更多日誌記錄 222
8.4.5 從devshell中運行命令 223
8.4.6 查看包的依賴關係 224
8.5 了解BitBake語法和語義 225
8.5.1 任務 225
8.5.2 依賴項 226
8.5.3 任務間依賴項 226
8.5.4 構建時依賴項 226
8.5.5 運行時依賴項 227
8.5.6 變數 228
8.5.7 賦值和擴展 228
8.5.8 附加和前置 229
8.5.9 覆蓋 229
8.5.10 內聯Python 230
8.5.11 函式 231
8.5.12 shell 231
8.5.13 Python 231
8.5.14 純Python函式 232
8.5.15 BitBake風格的Python函式 232
8.5.16 匿名Python函式 233
8.5.17 RDEPENDS 234
8.6 小結 235
8.7 延伸閱讀 235
第2篇 系統架構和設計決策
第9章 創建存儲策略 239
9.1 技術要求 239
9.2 存儲選項 240
9.2.1 NOR快閃記憶體 241
9.2.2 NAND快閃記憶體 241
9.2.3 託管快閃記憶體 243
9.2.4 多媒體卡和安全數字卡 244
9.2.5 eMMC 245
9.2.6 其他類型的託管快閃記憶體 245
9.3 從引導載入程式中訪問快閃記憶體 245
9.3.1 U-Boot和NOR快閃記憶體 246
9.3.2 U-Boot和NAND快閃記憶體 246
9.3.3 U-Boot和MMC、SD和eMMC 246
9.4 從Linux中訪問快閃記憶體 247
9.4.1 記憶體技術設備子系統 247
9.4.2 MTD分區 248
9.4.3 MTD設備驅動程式 251
9.4.4 MTD字元設備 251
9.4.5 MTD塊設備mtdblock 252
9.4.6 將核心錯誤記錄到MTD上 253
9.4.7 模擬NAND存儲器 253
9.4.8 MMC塊驅動程式 253
9.5 快閃記憶體檔案系統 254
9.5.1 快閃記憶體轉換層的特點 254
9.5.2 快閃記憶體轉換層的部署方式 255
9.6 NOR和NAND快閃記憶體的檔案系統 255
9.6.1 JFFS2 256
9.6.2 摘要節點 257
9.6.3 乾淨標記 257
9.6.4 創建JFFS2檔案系統 257
9.6.5 YAFFS2 258
9.6.6 創建YAFFS2檔案系統 259
9.6.7 UBI和UBIFS 260
9.6.8 UBI 260
9.6.9 UBIFS 263
9.7 託管快閃記憶體的檔案系統 264
9.7.1 Flashbench 265
9.7.2 丟棄和修剪 266
9.7.3 Ext4 267
9.7.4 F2FS 268
9.7.5 FAT16/32 268
9.8 唯讀壓縮檔案系統 269
9.8.1 SquashFS 269
9.8.2 在NAND快閃記憶體上使用SquashFS 269
9.9 臨時檔案系統 270
9.10 將根檔案系統設為唯讀 271
9.11 檔案系統選擇 272
9.12 小結 273
9.13 延伸閱讀 273
第10章 現場更新軟體 275
10.1 技術要求 275
10.2 啟動更新的方法 276
10.3 更新的內容 276
10.3.1 引導載入程式 277
10.3.2 核心 277
10.3.3 根檔案系統 278
10.3.4 系統應用程式 278
10.3.5 與特定設備相關的數據 278
10.3.6 需要更新的組件 279
10.4 有關軟體更新的基礎知識 279
10.4.1 使更新穩定可靠 279
10.4.2 使更新不受故障影響 280
10.4.3 確保更新安全 282
10.5 更新機制的類型 283
10.5.1 對稱鏡像更新 283
10.5.2 非對稱鏡像更新 285
10.5.3 原子檔案更新 286
10.6 OTA更新 288
10.7 使用Mender進行本地更新 288
10.7.1 構建Mender客戶端 289
10.7.2 安裝更新 291
10.8 使用Mender進行OTA更新 294
10.8.1 設定更新伺服器 294
10.8.2 上傳工件 297
10.8.3 部署更新 299
10.9 使用balena進行本地更新 301
10.9.1 創建一個賬戶 302
10.9.2 創建應用程式 303
10.9.3 添加設備 304
10.9.4 啟用本地模式 306
10.9.5 安裝CLI 307
10.9.6 推送一個項目 309
10.9.7 修改和更新項目 310
10.10 小結 311
第11章 連線設備驅動程式 313
11.1 技術要求 313
11.2 設備驅動程式的作用 314
11.3 字元設備 315
11.4 塊設備 317
11.5 網路設備 318
11.6 在運行時查找驅動程式 320
11.6.1 從sysfs中獲取信息 322
11.6.2 設備 322
11.6.3 驅動程式 323
11.6.4 塊驅動程式 324
11.7 尋找合適的設備驅動程式 325
11.8 用戶空間中的設備驅動程式 325
11.8.1 通用輸入/輸出接口 326
11.8.2 處理來自GPIO的中斷 327
11.8.3 LED 329
11.8.4 I2C 330
11.8.5 SPI 332
11.9 編寫核心設備驅動程式 333
11.9.1 設計字元設備驅動程式接口 333
11.9.2 對於設備驅動程式的剖析 335
11.9.3 編譯核心模組 338
11.9.4 載入核心模組 339
11.10 發現硬體配置 339
11.10.1 設備樹 340
11.10.2 平台數據 340
11.10.3 將硬體與設備驅動程式連結在一起 341
11.11 小結 343
11.12 延伸閱讀 344
第12章 使用分線板進行原型設計 345
12.1 技術要求 345
12.2 將原理圖映射到設備樹的源中 346
12.2.1 閱讀原理圖和數據表 347
12.2.2 在BeagleBone Black上安裝Debian 352
12.2.3 啟用spidev 353
12.2.4 自定義設備樹 359
12.3 使用分線板進行原型設計 367
12.3.1 閉合SPI跳線 368
12.3.2 安裝GNSS天線 370
12.3.3 附加SPI接頭 370
12.3.4 連線SPI跳線 371
12.4 使用邏輯分析儀探測SPI信號 375
12.4.1 連線邏輯分析儀 376
12.4.2 配置Logic 8 377
12.5 通過SPI接收NMEA訊息 383
12.6 小結 387
12.7 延伸閱讀 387
第13章 init程式 389
13.1 技術要求 389
13.2 核心引導後的操作 390
13.3 init程式簡介 391
13.4 BusyBox init 392
13.4.1 BusyBox init解析 392
13.4.2 Buildroot init腳本 393
13.5 System V init 393
13.5.1 inittab 395
13.5.2 init.d腳本 397
13.5.3 添加新的守護進程 398
13.5.4 啟動和停止服務 399
13.6 systemd 400
13.6.1 使用Yocto Project和Buildroot構建systemd 400
13.6.2 關於目標、服務和單元 401
13.6.3 單元 401
13.6.4 服務 402
13.6.5 目標 402
13.6.6 systemd引導系統的方式 403
13.6.7 添加自己的服務 404
13.6.8 添加看門狗 405
13.6.9 對嵌入式Linux的影響 406
13.7 小結 406
13.8 延伸閱讀 407
第14章 使用BusyBox runit啟動 409
14.1 技術要求 409
14.2 獲取BusyBox runit 410
14.3 創建服務目錄和檔案 416
14.3.1 服務目錄布局 417
14.3.2 服務配置 418
14.4 服務監督 425
14.4.1 runsv腳本運行的服務 425
14.4.2 控制服務 427
14.5 服務依賴 429
14.5.1 啟動依賴項 429
14.5.2 自定義啟動依賴項 431
14.5.3 簡單總結 431
14.6 專用服務日誌記錄 432
14.6.1 專用日誌記錄器的工作方式 432
14.6.2 向服務中添加專用日誌記錄 433
14.6.3 日誌輪轉 434
14.7 發出服務信號 435
14.8 小結 436
14.9 延伸閱讀 437
第15章 管理電源 439
15.1 技術要求 439
15.2 測量用電量 440
15.3 調整時鐘頻率 443
15.3.1 CPUFreq驅動程式 444
15.3.2 使用CPUFreq 446
15.4 選擇最佳空閒狀態 448
15.4.1 CPUIdle驅動程式 449
15.4.2 無滴答操作 452
15.5 關閉外圍設備 452
15.6 使系統進入休眠狀態 454
15.6.1 電源狀態 454
15.6.2 喚醒事件 455
15.6.3 從實時時鐘定時喚醒 456
15.7 小結 458
15.8 延伸閱讀 458
第3篇 編寫嵌入式應用程式
第16章 打包Python程式 461
16.1 技術要求 461
16.1.1 安裝venv 462
16.1.2 安裝Docker 462
16.2 追溯Python打包的起源 463
16.2.1 distutils 463
16.2.2 setuptools 463
16.2.3 setup.py 464
16.3 使用pip安裝Python包 466
16.3.1 pip和pip3 466
16.3.2 requirements.txt 469
16.4 使用venv管理Python虛擬環境 471
16.4.1 venv 472
16.4.2 創建虛擬環境 473
16.4.3 激活和驗證虛擬環境 473
16.4.4 在虛擬環境中安裝測試庫 474
16.5 使用conda安裝預編譯的二進制檔案 475
16.5.1 環境管理 475
16.5.2 驗證根環境 476
16.5.3 創建conda環境 477
16.5.4 包管理 478
16.5.5 導出虛擬環境 479
16.6 使用Docker部署Python應用程式 480
16.6.1 Dockerfile解析 481
16.6.2 構建Docker鏡像 483
16.6.3 運行Docker鏡像 484
16.6.4 提取Docker鏡像 485
16.6.5 發布Docker鏡像 485
16.6.6 刪除Docker容器 486
16.6.7 刪除Docker鏡像 487
16.6.8 Docker套用總結 487
16.7 小結 488
16.8 延伸閱讀 488
第17章 了解進程和執行緒 489
17.1 技術要求 489
17.2 進程和執行緒的抉擇 490
17.3 進程 492
17.3.1 創建新進程 492
17.3.2 終止進程 493
17.3.3 運行不同的程式 494
17.3.4 守護進程 497
17.3.5 進程間通信 497
17.3.6 基於訊息的IPC 498
17.3.7 UNIX套接字 498
17.3.8 FIFO和命名管道 499
17.3.9 POSIX訊息佇列 499
17.3.10 基於訊息的IPC總結 499
17.3.11 基於共享記憶體的IPC 500
17.3.12 POSIX共享記憶體 500
17.4 執行緒 503
17.4.1 創建一個新執行緒 503
17.4.2 終止執行緒 505
17.4.3 用執行緒編譯程式 505
17.4.4 執行緒間通信 505
17.4.5 互斥鎖 506
17.4.6 不斷變化的條件 506
17.4.7 進程和執行緒套用規則 508
17.5 ZeroMQ 509
17.5.1 獲取pyzmq 510
17.5.2 進程之間的訊息傳遞 510
17.5.3 進程內的訊息傳遞 512
17.6 調度 514
17.6.1 公平與確定性 514
17.6.2 分時策略 515
17.6.3 nice值 516
17.6.4 實時策略 516
17.6.5 選擇策略 517
17.6.6 選擇實時優先權 518
17.7 小結 518
17.8 延伸閱讀 518
第18章 管理記憶體 521
18.1 技術要求 521
18.2 虛擬記憶體基礎知識 522
18.3 核心空間記憶體布局 523
18.3.1 核心日誌訊息分析 523
18.3.2 核心的記憶體使用情況 524
18.4 用戶空間記憶體布局 526
18.5 進程記憶體映射 528
18.6 交換 529
18.6.1 交換的利弊 529
18.6.2 交換到壓縮記憶體 530
18.7 使用mmap映射記憶體 530
18.7.1 使用mmap分配私有記憶體 531
18.7.2 使用mmap共享記憶體 531
18.7.3 使用mmap訪問設備記憶體 532
18.8 應用程式的記憶體使用情況 532
18.9 每個進程的記憶體使用情況 533
18.9.1 使用top和ps 534
18.9.2 使用smem 534
18.9.3 其他工具 536
18.10 識別記憶體泄漏 537
18.10.1 mtrace 537
18.10.2 Valgrind 538
18.11 記憶體不足 540
18.12 小結 541
18.13 延伸閱讀 542
第4篇 調試和最佳化性能
第19章 使用GDB進行調試 545
19.1 技術要求 545
19.2 GNU調試器 546
19.3 準備調試 547
19.4 調試應用程式 547
19.4.1 使用gdbserver進行遠程調試 548
19.4.2 設定Yocto Project以進行遠程調試 549
19.4.3 為遠程調試設定Buildroot 550
19.5 啟動調試 550
19.5.1 連線GDB和gdbserver 550
19.5.2 設定sysroot 551
19.5.3 GDB命令檔案 553
19.5.4 GDB命令概述 554
19.5.5 運行到斷點 555
19.5.6 用Python擴展GDB 556
19.5.7 構建包含Python支持的GDB 556
19.5.8 使用GDB遠程調試bsdiff 559
19.6 本機調試 560
19.6.1 Yocto Project 560
19.6.2 Buildroot 561
19.7 即時調試 561
19.8 調試分叉和執行緒 562
19.9 核心檔案 562
19.9.1 觀察核心檔案 563
19.9.2 使用GDB查看核心檔案 564
19.10 GDB用戶界面 565
19.10.1 終端用戶界面 565
19.10.2 數據顯示調試器 566
19.11 Visual Studio Code 567
19.11.1 安裝Visual Studio Code 567
19.11.2 安裝工具鏈 567
19.11.3 安裝CMake 569
19.11.4 創建一個Visual Studio Code項目 569
19.11.5 安裝Visual Studio Code擴展 569
19.11.6 配置CMake 570
19.11.7 配置項目設定 571
19.11.8 配置遠程調試的啟動設定 573
19.12 調試核心代碼 574
19.12.1 使用kgdb調試核心代碼 575
19.12.2 調試會話示例 576
19.12.3 調試早期代碼 577
19.12.4 調試模組 578
19.12.5 使用kdb調試核心代碼 579
19.12.6 查看核心Oops訊息 580
19.12.7 保存Oops訊息 583
19.13 小結 584
19.14 延伸閱讀 585
第20章 性能分析和跟蹤 587
20.1 技術要求 588
20.2 觀察者效應 588
20.2.1 關於觀察者效應 588
20.2.2 符號表和編譯標誌 589
20.3 開始性能分析 589
20.4 使用top進行性能分析 590
20.5 窮人的性能分析器 591
20.6 perf簡介 592
20.6.1 為perf配置核心 593
20.6.2 使用Yocto Project構建perf 593
20.6.3 使用Buildroot構建perf 594
20.6.4 使用perf進行性能分析 594
20.6.5 調用圖 596
20.6.6 perf annotate 597
20.7 跟蹤事件 598
20.8 Ftrace簡介 599
20.8.1 準備使用Ftrace 599
20.8.2 使用Ftrace 600
20.8.3 動態Ftrace和跟蹤過濾器 602
20.8.4 跟蹤事件 603
20.9 使用LTTng 604
20.9.1 LTTng和Yocto Project 605
20.9.2 LTTng和Buildroot 605
20.9.3 使用LTTng進行核心跟蹤 606
20.10 使用BPF 608
20.10.1 為BPF配置核心 608
20.10.2 使用Buildroot構建BCC工具包 611
20.10.3 使用BPF跟蹤工具 612
20.11 使用Valgrind 615
20.11.1 Callgrind 615
20.11.2 Helgrind 616
20.12 使用strace 616
20.13 小結 619
20.14 延伸閱讀 619
第21章 實時編程 621
21.1 技術要求 621
21.2 關於實時 622
21.3 識別非確定性的來源 624
21.4 了解調度延遲 625
21.5 核心搶占 626
21.5.1 實時Linux核心(PREEMPT_RT) 627
21.5.2 執行緒化中斷處理程式 628
21.6 可搶占核心鎖 630
21.6.1 獲取PREEMPT_RT補丁 631
21.6.2 Yocto Project和PREEMPT_RT 632
21.7 高解析度定時器 632
21.8 避免頁面錯誤 633
21.9 中斷禁止 634
21.10 測量調度延遲 634
21.10.1 cyclictest 635
21.10.2 使用Ftrace 638
21.10.3 結合cyclictest和Ftrace 639
21.11 小結 640
21.12 延伸閱讀 641