精通嵌入式 Linux 編程, 3/e Mastering Embedded Linux Programming, 3/e

[美]弗蘭克·瓦斯奎茲 等著 陳會翔 譯

  • 精通嵌入式 Linux 編程, 3/e-preview-1
  • 精通嵌入式 Linux 編程, 3/e-preview-2
  • 精通嵌入式 Linux 編程, 3/e-preview-3
精通嵌入式 Linux 編程, 3/e-preview-1

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

相關主題

商品描述

《精通嵌入式Linux編程》詳細闡述了與嵌入式Linux開發相關的基本解決方案,主要包括初識嵌入式Linux開發、關於工具鏈、引導加載程序詳解、配置和構建內核、構建根文件系統、選擇構建系統、使用Yocto進行開發、Yocto技術內幕、創建存儲策略、現場更新軟件、連接設備驅動程序、使用分線板進行原型設計、init程序、使用BusyBox runit啟動、管理電源、打包Python程序、瞭解進程和線程、管理內存、使用GDB進行調試、性能分析和跟蹤、實時編程等內容。此外,本書還提供了相應的示例、代碼,以幫助讀者進一步理解相關方案的實現過程。 本書適合作為高等院校電腦及相關專業的教材和教學參考書,也可作為相關開發人員的自學用書和參考手冊。

作者簡介

弗蘭克·瓦斯奎茲是一位專注於消費電子產品的獨立軟件顧問。他在設計和構建嵌入式Linux系統方面擁有十多年的經驗。在此期間,他完成了許多設備的開發,包括機架式DSP音頻服務器、潛水員手持式聲納攝像機和消費者物聯網熱點。在成為嵌入式Linux開發工程師之前,Frank曾經是IBM的數據庫內核開發人員,他在該公司主要從事DB2方面的工作。他目前住在矽谷。

目錄大綱

目    錄

第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