第1章 体验嵌入式系统的魅力 1
1.1 嵌入式系统的定义 2
1.2 嵌入式系统的历史与现状 2
1.2.1 无操作系统阶段 2
1.2.2 简单操作系统阶段 3
1.2.3 实时操作系统阶段 3
1.2.4 面向Internet阶段 3
1.3 嵌入式与非嵌入式的区别 4
1.4 从事嵌入式软件开发的前景 4
1.4.1 优势 4
1.4.2 从事嵌入式软件开发的缺点 5
1.4.3 技术基本要求 6
1.5 嵌入式系统的体系结构 6
1.5.1 嵌入式处理器 6
1.5.2 嵌入式外围设备 7
1.5.3 嵌入式操作系统 8
1.5.4 嵌入式应用软件 9
1.6 ARM 9
1.7 延伸阅读:嵌入式系统面临的关键问题 10
1.8 小结 11
第2章 嵌入式Linux的前世今生 13
2.1 嵌入式Linux简介 14
2.1.1 嵌入式Linux的优势 14
2.1.2 嵌入式Linux面临的挑战 15
2.1.3 发展前景 16
2.1.4 Android 17
2.2 嵌入式Linux系统的软件组成 17
2.2.1 引导加载程序 17
2.2.2 Linux内核 18
2.2.3 文件系统 19
2.2.4 用户应用程序 21
2.3 嵌入式系统软件研发的关键技术 21
2.3.1 开发流程 21
2.3.2 交叉编译和链接 22
2.3.3 交叉调试 23
2.3.4 系统测试 25
2.4 系统启动过程 26
2.5 延伸阅读:开源、GPL与POSIX简介 28
2.5.1 开源 28
2.5.2 GPL 29
2.5.3 POSIX 30
2.6 小结 32
第3章 零基础安装虚拟机与Linux操作系统 33
3.1 VMware Workstation的安装 34
3.2 配置VMware Workstation并便捷安装Fedora 16 36
3.3 配置VMware Workstation手动安装Fedora 16 43
3.4 安装Fedora 16 47
3.5 VMware Tools的安装 52
3.6 使用已安装好操作系统的虚拟机 56
3.7 延伸阅读:打开Fedora 16的root账号 58
3.8 小结 58
第4章 快速构建嵌入式Linux开发环境 59
4.1 安装交叉编译器 60
4.1.1 安装交叉编译器 60
4.1.2 建立链接 62
4.1.3 查看交叉工具是否安装正确 63
4.2 构建开发板运行所需的环境 63
4.2.1 编译一级启动文件x-loader 63
4.2.2 编译二级启动文件U-Boot 65
4.2.3 编译内核 67
4.2.4 制作文件系统镜像 68
4.3 更新系统文件 69
4.3.1 更新文件从SD卡启动 69
4.3.2 更新文件从NAND Flash启动 70
4.4 小结 77
第5章 配置串口通信工具 79
5.1 配置Windows XP的超级终端 80
5.2 串口信息的捕获 82
5.3 在Linux中配置Minicom 84
5.4 小结 88
第6章 配置NFS文件系统服务 89
6.1 查看宿主机上的安装包 90
6.2 配置网络文件系统NFS 91
6.3 启动NFS服务 91
6.3.1 在Fedora 16下面运行service nfs start命令失败 91
6.3.2 在Fedora 16下面运行service nfs-server start失败 92
6.4 本机测试NFS 94
6.5 在开发板上测试NFS 94
6.5.1 常见的测试过程 94
6.5.2 NFS无法挂载的问题分析 95
6.6 小结 96
第7章 开始编写第一个程序 97
7.1 在宿主机上编写第一个程序 98
7.2 编写开发板上的上第一个程序 99
7.3 小结 102
第8章 Linux开发入门必备私房菜 103
8.1 程序安装目录 104
8.2 头文件 104
8.3 库文件 104
8.4 gcc简介 106
8.5 make简介 107
8.6 小结 109
第9章 Shell:用户与Linux沟通的桥梁 111
9.1 Shell是如何工作的 112
9.2 Shell的“兄弟姐妹” 113
9.3 必须熟悉的Shell命令 114
9.3.1 命令行 114
9.3.2 选项和参数 115
9.3.3 命令行特征 116
9.4 理解Shell中的特殊字符 116
9.4.1 通配符 116
9.4.2 引号 118
9.4.3 注释符 119
9.5 畅通交流:标准输入/输出和重定向 120
9.5.1 标准输入与输出 120
9.5.2 输入重定向 121
9.5.3 输出重定向 122
9.5.4 管道 124
9.6 命令替换 124
9.7 实战体验:在Bash中的操作 125
9.7.1 命令和文件名扩展特性 125
9.7.2 命令行编辑 126
9.7.3 命令历史 126
9.7.4 命令别名 128
9.8 定制Bash 129
9.9 小结 129
第10章 文本编辑利器Vi 131
10.1 Vi简介 132
10.1.1 命令行模式 132
10.1.2 文本输入模式 132
10.1.3 末行模式 132
10.1.4 模式之间的切换 133
10.2 Vi的进入与退出 133
10.2.1 Vi的进入 133
10.2.2 退出Vi 134
10.3 Vi中的行号 135
10.4 光标移动操作 136
10.5 按字移动光标 138
10.5.1 w和W命令 138
10.5.2 e和E命令 139
10.5.3 b和B命令 139
10.6 屏幕滚动 139
10.6.1 滚屏命令 139
10.6.2 分页命令 139
10.6.3 状态命令 140
10.7 屏幕调零命令 140
10.8 文本插入操作 140
10.8.1 插入(Insert)命令 140
10.8.2 打开(open)命令 141
10.9 文本修改 142
10.9.1 文本删除 142
10.9.2 取消上一命令(Undo) 143
10.9.3 重复命令(Redo) 144
10.10 实现替换功能 145
10.11 小结 145
第11章 应知应会的基本函数 147
11.1 文件操作函数 148
11.1.1 文件的创建与打开操作 148
11.1.2 对文件进行读写 149
11.1.3 文件的关闭操作 150
11.1.4 改变文件读写偏移位置:lseek() 150
11.1.5 实例:文件的打开关闭、读写与设置文件读写指针 151
11.1.6 文件描述符和流 152
11.1.7 文件控制操作函数fcntl() 154
11.1.8 控制设备文件参数的函数ioctl() 154
11.1.9 文件的权限修改 154
11.1.10 文件的属主与组群修改 156
11.1.11 获得文件的状态 157
11.1.12 文件的其他操作 160
11.2 目录操作 161
11.2.1 创建和删除目录的函数 161
11.2.2 打开目录 161
11.2.3 读取目录 162
11.2.4 关闭目录 163
11.2.5 改变工作目录的函数 163
11.2.6 取得当前的工作目录 163
11.2.7 实例:文件列表程序 164
11.3 建立临时文件 165
11.4 获取进程号 170
11.5 获取节点信息 170
11.6 小结 173
第12章 时间问题的处理 175
12.1 时钟类型 176
12.1.1 硬件时钟 176
12.1.2 系统时钟 176
12.1.3 系统时钟与硬件时钟的关系 176
12.2 UTC、CST与GMT 176
12.3 Linux下常用的时间类型 177
12.3.1 time t时间类型 177
12.3.2 struct tm时间类型 177
12.3.3 struct timeval时间类型 178
12.3.4 struct timespec时间类型 178
12.3.5 struct timezone 179
12.3.6 获得自Epoch以来的秒数 179
12.4 获得与修改系统时间 180
12.5 时间格式转换 182
12.5.1 asctime函数 182
12.5.2 ctime函数 183
12.5.3 gmtime函数 184
12.5.4 localtime函数 185
12.5.5 mktime函数 186
12.6 使线程睡眠的时间函数 186
12.6.1 sleep函数 186
12.6.2 usleep函数 188
12.6.3 nanosleep函数 189
12.6.4 示例:为nanosleep()函数指定秒数和纳秒数 190
12.6.5 alarm函数 192
12.7 延伸阅读:其他函数 193
12.8 小结 194
第13章 简单的网络编程实战 195
13.1 基础知识 196
13.1.1 C/S与B/S结构 196
13.1.2 UDP/TCP协议 197
13.1.3 什么是Socket 198
13.2 UDP套接字编程实例 198
13.2.1 服务端 198
13.2.2 客户端 200
13.2.3 编译 202
13.2.4 运行结果 203
13.2.5 使用Wireshark捕获数据包 203
13.2.6 UDP套接字网络编程涉及的系统调用过程 204
13.2.7 建立Socket 206
13.2.8 配置Socket 206
13.2.9 数据传输 208
13.2.10 延伸阅读:关闭Socket 209
13.3 TCP套接字编程实例 209
13.3.1 服务端 209
13.3.2 客户端 212
13.3.3 编译 214
13.3.4 运行结果 214
13.3.5 使用Wireshark捕获数据包 215
13.3.6 TCP套接字网络编程所涉及的系统函数 216
13.3.7 建立连接 217
13.3.8 数据传输 219
13.4 小结 220
第14章 简单的线程操作实战 221
14.1 为何嵌入式系统中进程不再是重点 222
14.1.1 进程与线程 222
14.1.2 线程的优势 222
14.1.3 我们的问题 223
14.1.4 进程通信的统一方式:Socket通信 224
14.1.5 简单的线程操作 224
14.2 创建线程 227
14.3 获得本线程的标识符 228
14.4 结束线程 228
14.5 延伸阅读:操作线程共享变量 229
14.6 小结 232
第15章 重点剖析:线程同步实例 233
15.1 互斥锁 234
15.1.1 再谈线程共享变量的操作 235
15.1.2 互斥锁的创建 237
15.1.3 互斥锁的销毁 238
15.1.4 互斥锁的操作 238
15.2 读写锁 239
15.2.1 读写锁实例 239
15.2.2 读写锁的创建 241
15.2.3 获取读写锁中的读锁 242
15.2.4 获取读写锁中的写锁 243
15.2.5 解除锁定的读写锁 243
15.2.6 销毁读写锁 244
15.3 条件变量 245
15.3.1 忙等待 245
15.3.2 条件变量 247
15.3.3 条件变量的创建 249
15.3.4 条件变量的销毁 249
15.3.5 条件变量的等待和激发 249
15.3.6 互斥锁和条件变量的结合使用 250
15.4 线程死锁 253
15.5 延伸阅读:解决死锁的方法 255
15.5.1 解决方法一 255
15.5.2 解决方法二 256
15.6 小结 258
第16章 进阶私房菜:再谈线程 259
16.1 线程参数的传递 260
16.1.1 单个参数传递 260
16.1.2 多个参数传递 261
16.2 线程私有数据 263
16.2.1 创建key 266
16.2.2 删除key 267
16.2.3 读写key 267
16.3 修改线程属性 267
16.3.1 可以修改的线程属性 268
16.3.2 修改线程参数示例 271
16.4 延伸阅读:线程池 275
16.4.1 为什么需要线程池 275
16.4.2 构建线程池框架 276
16.4.3 简单的线程池示例 276
16.5 小结 285
第17章 进阶私房菜:再谈网络编程 287
17.1 对SIGPIPE信号的处理 288
17.1.1 示例1:SIGPIPE信号的默认处理 288
17.1.2 示例2:重定义SIGPIPE信号的默认动作 293
17.1.3 示例3:忽略SIGPIPE信号 295
17.1.4 示例4:直接使用MSG_NOSIGNAL标识 296
17.2 修改Socket缓冲区的大小 297
17.2.1 setsockopt函数与getsockopt函数 297
17.2.2 示例:修改Socket缓冲区的大小 299
17.3 检测服务器与客户端的连接是否有效 302
17.4 服务器的多线程处理 304
17.4.1 客户端 305
17.4.2 服务器 309
17.5 延伸阅读:重新bind 312
17.5.1 TIME WAIT的两个作用 312
17.5.2 如何结束TIME WAIT状态 313
17.5.3 实现可立即重启的服务器 314
17.6 小结 315
第18章 重点突破:网络编程的字节流处理 317
18.1 面向字节流的分包问题 318
18.1.1 数据包的常见结构 318
18.1.2 线程间数据的交互——环形缓冲区的实现 319
18.1.3 环形缓冲区 319
18.1.4 封包与解包 328
18.1.5 网络整合使用实例 329
18.1.6 错误数据包的测试 335
18.2 再谈生产者与消费者的示例 346
18.3 小结 352
第19章 嵌入式B/S架构开发要点 353
19.1 几种嵌入式Web服务器的比较 354
19.1.1 Boa 354
19.1.2 thttpd 354
19.1.3 Mimi_httpd 355
19.1.4 Mongoose 355
19.1.5 Lighttpd 356
19.1.6 AppWeb 356
19.1.7 Apache 357
19.2 Boa简介 357
19.3 移植与测试Boa的环境配置 358
19.4 Boa的移植 358
19.4.1 下载源代码 358
19.4.2 编译 358
19.4.3 安装到开发板的Linux文件系统 360
19.4.4 配置 361
19.4.5 测试 361
19.5 使用CGI 363
19.5.1 简介 363
19.5.2 配置目标板文件系统 363
19.5.3 编写HelloCGI.c程序 364
19.5.4 交叉编译 364
19.5.5 测试 364
19.6 复杂网页测试 367
19.6.1 设置目标板文件系统/var/www的目录结构 367
19.6.2 编制index.html 368
19.6.3 测试 369
19.7 小结 371
第20章 SQLite数据库移植与实战 373
20.1 SQLite的特性 374
20.2 SQLite的移植过程 374
20.2.1 移植的环境 374
20.2.2 移植步骤 375
20.3 如何使用Linux C操作SQLite 376
20.4 数据库的并发访问 379
20.5 小结 384
附录A 网络分析工具Wireshark的使用 385