精通嵌入式LINUX编程
- ISBN:9787302635635
- 装帧:平装-胶订
- 册数:暂无
- 重量:暂无
- 开本:其他
- 页数:641
- 出版时间:2023-06-01
- 条形码:9787302635635 ; 978-7-302-63563-5
本书特色
多年来,Linux一直是嵌入式计算的中流砥柱。然而,涵盖该领域所有主题的书籍非常少,本书旨在填补这一空白。“嵌入式Linux”一词的定义并不明确,它可以应用于从恒温器到Wi-Fi路由器,再到工业控制单元的各种设备内的操作系统。但是,它们都建立在相同的基本开源软件之上。这些正是我们在本书中要描述的技术,本书的写作基于我们作为工程师的经验和为培训课程开发的资料。
内容简介
《精通嵌入式Linux编程》详细阐述了与嵌入式Linux开发相关的基本解决方案,主要包括初识嵌入式Linux开发、关于工具链、引导加载程序详解、配置和构建内核、构建根文件系统、选择构建系统、使用Yocto进行开发、Yocto技术内幕、创建存储策略、现场更新软件、连接设备驱动程序、使用分线板进行原型设计、init程序、使用BusyBox runit启动、管理电源、打包Python程序、了解进程和线程、管理内存、使用GDB进行调试、性能分析和跟踪、实时编程等内容。此外,本书还提供了相应的示例、代码,以帮助读者进一步理解相关方案的实现过程。 本书适合作为高等院校计算机及相关专业的教材和教学参考书,也可作为相关开发人员的自学用书和参考手册。
目录
第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
作者简介
弗兰克·瓦斯奎兹是一位专注于消费电子产品的独立软件顾问。他在设计和构建嵌入式Linux系统方面拥有十多年的经验。在此期间,他完成了许多设备的开发,包括机架式DSP音频服务器、潜水员手持式声纳摄像机和消费者物联网热点。在成为嵌入式Linux开发工程师之前,Frank曾经是IBM的数据库内核开发人员,他在该公司主要从事DB2方面的工作。他目前住在硅谷。
-
全图解零基础word excel ppt 应用教程
¥15.6¥48.0 -
有限与无限的游戏:一个哲学家眼中的竞技世界
¥37.4¥68.0 -
零信任网络:在不可信网络中构建安全系统
¥37.2¥59.0 -
硅谷之火-人与计算机的未来
¥20.3¥39.8 -
情感计算
¥66.8¥89.0 -
大模型RAG实战 RAG原理、应用与系统构建
¥69.3¥99.0 -
LINUX企业运维实战(REDIS+ZABBIX+NGINX+PROMETHEUS+GRAFANA+LNMP)
¥52.4¥69.0 -
AI虚拟数字人:商业模式+形象创建+视频直播+案例应用
¥68.2¥89.8 -
LINUX实战——从入门到精通
¥49.0¥69.0 -
UNIX环境高级编程(第3版)
¥164.9¥229.0 -
剪映AI
¥52.8¥88.0 -
快速部署大模型:LLM策略与实践(基于ChatGPT等大语言模型)
¥56.9¥79.0 -
数据驱动的工业人工智能:建模方法与应用
¥68.3¥99.0 -
深度学习高手笔记 卷2:经典应用
¥90.9¥129.8 -
纹样之美:中国传统经典纹样速查手册
¥81.8¥109.0 -
UG NX 12.0数控编程
¥24.8¥45.0 -
MATLAB计算机视觉与深度学习实战(第2版)
¥90.9¥128.0 -
UN NX 12.0多轴数控编程案例教程
¥24.3¥38.0 -
做好课题申报:AI辅助申请书写作
¥48.9¥69.8 -
微机组装与系统维护技术教程(第二版)
¥37.8¥43.0