关于我们
![]() ![]() |
高质量嵌入式Linux C编程(第2版) 读者对象:本书既可作为大专院校相关专业师生的教学参考书,也可供计算机及其相关领域的工程技术人员查阅之用,对于普通计算机爱好者,本书也不失为帮助他们掌握嵌入式Linux C高质量系统开发的一本深入浅出的嵌入式开发读物。
本书从嵌入式开发角度出发,以Linux操作系统为开发平台,将隐藏在系统开发背后的关于C语言、数据结构与算法、计算机组成原理、计算机操作系统、数据库原理等方面的机制和知识娓娓道来,不仅让读者知其然,更要让读者知其所以然,并让这些知识再反作用于编程实践,从而帮助读者写出高质量的嵌入式Linux C代码,揭开嵌入式Linux C系统开发背后鲜为人知的秘密。
梁庚,男,毕业于四川大学软件工程专业,现为南京优奈特信息科技有限公司研发工程师,南京工业大学外聘讲师,金陵科技学院外聘讲师,主要从事嵌入式系统的研发工作。
第 1 章 嵌入式Linux C 语言开发工具··········································································(1)
1.1 嵌入式Linux C 语言开发概述·················································································(1) 1.2 嵌入式Linux C 开发环境·······················································································(2) 1.3 嵌入式文本编辑器··························································································(2) 1.3.1 基本模式································································································. (3) 1.3.2 基本操作··································································································(3) 1.3.3 实训操作··································································································(5) 1.4 嵌入式编译器······································································································(6) 1.4.1 初识GCC 编译器························································································(6) 1.4.2 gcc 命令常用选项和工作流程·········································································(6) 1.4.3 库的使用·······························································································.(10) 1.5 嵌入式调试器···································································································.(12) 1.6 工程管理器······································································································.(15) 1.6.1 Makefile·································································································.(16) 1.6.2 Makefile 特性介绍····················································································.(18) 1.7 Eclipse 程序开发·······························································································.(27) 1.7.1 Eclipse 环境安装······················································································.(27) 1.7.2 Eclipse C 程序开发···················································································.(29) 1.8 软件版本管理···································································································.(34) 1.8.1 Git 版本管理···························································································.(34) 1.8.2 Ubuntu 软件包管理···················································································.(45) 第 2 章 数据类型··································································································.(48) 2.1 变量与常量······································································································.(48) 2.2 变量···············································································································.(48) 2.2.1 什么是变量····························································································.(48) 2.2.2 变量名和变量值······················································································.(49) 2.2.3 局部变量和全局变量················································································.(51) 2.3 常量···············································································································.(53) 2.4 基本内置类型···································································································.(54) 2.4.1 数据类型及其大小···················································································.(55) 2.4.2 陷阱——有符号与无符号·············································································.(55) 2.5 声明与定义······································································································.(56) 2.5.1 定义·····································································································.(56) 2.5.2 声明·····································································································.(57) 2.6 static 与extern····················································································.(57) 2.6.1 static ························································································.(57) 2.6.2 extern ······································································.·······.·······.(59) 2.7 const ··································································································.(60) 2.8 auto·································································································.(61) 2.9 register·····························································································.(62) 2.10 volatile ···························································································.(63) 2.11 typedef 详解····································································································.(64) 2.11.1 typedef 与结构的问题··············································································.(64) 2.11.2 typedef 与#define 的问题··········································································.(66) 2.11.3 typedef 与#define 的另一例·······································································.(67) 2.11.4 typedef 与复杂的变量声明········································································.(67) 2.12 枚举(enum)·································································································.(68) 2.12.1 枚举类型的使用方法···············································································.(68) 2.12.2 枚举与#define 宏的区别··········································································.(69) 2.13 联合体··········································································································.(69) 2.13.1 联合体的定义························································································.(69) 2.13.2 从两道经典试题谈联合体(union)的使用···················································.(70) 第 3 章 运算符和表达式·····················································································(73) 3.1 运算符简介································································································.(73) 3.1.1 运算符优先级·························································································.(73) 3.1.2 一些容易出错的优先级问题·······································································.(75) 3.1.3 逻辑运算符····························································································.(76) 3.2 条件运算符和条件表达式····················································································.(76) 3.3 ++、--操作符···································································································.(77) 3.4 位运算············································································································.(78) 3.4.1 按位与运算及应用···················································································.(78) 3.4.2 按位或运算及应用···················································································.(79) 3.4.3 按位异或运算及应用················································································.(79) 3.4.4 左移和右移····························································································.(79) 3.5 C 语言性能优化:使用位操作········································································.(79) 第 4 章 语句···································································································.(81) 4.1 空语句·······································································································.(81) 4.2 基础语句···································································································.(82) 4.2.1 表达式语句····························································································. (82) 4.2.2 函数调用语句·························································································.(82) 4.3 if 语句······································································································.(82) 4.3.1 布尔变量与零值的比较·············································································.(83) 4.3.2 整型变量与零值比较················································································.(83) 4.3.3 浮点变量与零值的比较·············································································.(83) 4.3.4 指针变量与零值的比较·············································································.(84) 4.3.5 对if 语句的补充说明················································································.(84) 4.4 跳转语句:goto ································································································.(85) 4.5 循环语句·········································································································.(85) 4.5.1 do-while 语句··························································································.(86) 4.5.2 for 语句·································································································.(86) 4.5.3 循环语句的效率······················································································.(88) 4.6 break 和continue ·······················································································.(89) 4.6.1 break 语句······························································································.(89) 4.6.2 continue 语句··························································································.(90) 4.7 switch 语句·································································································.(91) 第 5 章 数组与指针···························································································.(92) 5.1 数组认知·····································································································.(92) 5.2 使用数组的常见问题······················································································.(93) 5.2.1 数组的下标总是从0 开始吗··························································. ············.(93) 5.2.2 可以使用数组后面第一个元素的地址吗···············································. ········.(94) 5.2.3 为什么要小心对待位于数组后面的那些元素的地址呢··········································.(95) 5.2.4 当数组作为参数传递给函数时,可以通过sizeof 得到数组的大小吗························.(95) 5.2.5 指针或带下标的数组名都可以访问元素,哪一种更好呢···································.····(96) 5.2.6 可以把另外一个地址赋给一个数组名吗·····························································(98) 5.2.7 array_name 和&array_name 有什么不同·························································.(99) 5.2.8 为什么用const 说明的常量不能用来定义一个数组的初始大小····························(100) 5.2.9 字符串和数组有什么不同··········································································(100) 5.3 指针···············································································································(102) 5.3.1 指针是变量····························································································(103) 5.3.2 指针的类型和指针所指向的类型·································································(103) 5.3.3 指针的值·······························································································(104) 5.3.4 指针本身所占据的内存·············································································(105) 5.4 指针的运算······································································································(105) 5.4.1 指针的算术运算······················································································(105) 5.4.2 指针的关系运算······················································································(106) 5.4.3 间接引用·······························································································(106) 5.4.4 最多可以使用几层指针·············································································(106) 5.5 常量指针和指针常量··························································································(108) 5.5.1 常量指针与指针常量的实例·······································································(108) 5.5.2 常量指针的应用······················································································(109) 5.6 空指针及其使用································································································(110) 5.6.1 NULL 总是被定义为0 吗···········································································(110) 5.6.2 NULL 总是等于0 吗·················································································(110) 5.6.3 空指针的使用·························································································(111) 5.7 void 指针:万能指针··························································································(113) 5.8 指针数组与数组指针··························································································(114) 5.9 字符串函数详解································································································(114) 5.10 函数指针与指针函数························································································(119) 5.11 复杂指针声明:“int * (* (*fp1) (int) ) [10];” ···························································(120) 5.11.1 基础····································································································(120) 5.11.2 const 修饰符··························································································(121) 5.11.3 typedef 的妙用·······················································································(122) 5.11.4 函数指针······························································································(123) 5.11.5 右左法则······························································································(123) 第 6 章 内存管理································································································(125) 6.1 数据放在哪里···································································································(125) 6.1.1 未初始化的全局变量(.bss 段) ··································································(125) 6.1.2 初始化过的全局变量(.data 段) ·································································(126) 6.1.3 常量数据(.rodata 段) ·············································································(126) 6.1.4 代码(.text 段) ······················································································(127) 6.1.5 栈(stack) ····························································································(127) 6.1.6 堆(heap)·····························································································(127) 6.2 内存分配方式···································································································(128) 6.3 野指针············································································································(129) 6.4 常见的内存错误及对策·······················································································(129) 6.5 段错误及其调试方法··························································································(130) 6.5.1 方法一:利用gdb 逐步查找段错误······························································(131) 6.5.2 方法二:分析core 文件·············································································(131) 6.5.3 方法三:在发生段错误时启动调试······························································(132) 6.5.4 方法四:利用backtrace 和objdump 进行分析·················································(134) 6.6 指针与数组的对比·····························································································(135) 第 7 章 预处理和结构体···························································································(138) 7.1 宏定义:#define································································································(138) 7.1.1 无参宏定义····························································································(138) 7.1.2 带参宏定义····························································································(140) 7.2 文件包含·········································································································(141) 7.3 条件编译·········································································································(142) 7.4 宏定义的使用技巧·····························································································(144) 7.5 关于#和## ·······································································································(146) 7.6 结构体(struct) ·······························································································(147) 7.6.1 内存字节对齐·························································································(149) 7.6.2 内存对齐的正式原则················································································(152) 7.7 #define 和typedef 的区别·····················································································(152) 7.8 结构体(struct)和联合体(union)的区别·····························································(153) 7.9 浅谈C 语言中的位段·························································································(153) 7.9.1 位段的使用····························································································(154) 7.9.2 位段结构在内存中的存储方式····································································(154) 第 8 章 函数········································································································(155) 8.1 函数声明与定义································································································(155) 8.1.1 定义·····································································································(155) 8.1.2 声明与定义不同······················································································(156) 8.2 形式参数和实际参数··························································································(157) 8.3 参数传递·········································································································(157) 8.3.1 简单变量或数组元素作为函数参数······························································(157) 8.3.2 指针变量或数组名作为函数参数·································································(158) 8.3.3 数组名作为函数参数················································································(159) 8.3.4 结构体数组作为函数参数··········································································(160) 8.4 如何编写有多个返回值的C 语言函数····································································(160) 8.4.1 利用全局变量·························································································(161) 8.4.2 传递数组指针·························································································(162) 8.4.3 传递结构体指针······················································································(162) 8.5 回调函数·········································································································(163) 8.6 变参函数详解:printf 函数的实现·········································································(165) 8.7 可变参数的相关问题··························································································(166) 第 9 章 编码规范··································································································(170) 9.1 排版···············································································································(170) 9.2 注释···············································································································(173) 9.3 标示符名称······································································································(178) 第 10 章 shell 编程································································································(181) 10.1 什么是shell ····································································································(181) 10.2 几种流行的shell ······························································································(181) 10.3 shell 程序设计(基础部分) ···········································································(182) 10.3.1 shell 的基本语法·····················································································(182) 10.3.2 shell 程序的变量和参数············································································(183) 10.4 shell 程序设计的流程控制··················································································(185) 10.4.1 test 命令·······························································································(185) 10.4.2 if 条件语句···························································································(186) 10.4.3 for 循环································································································(187) 10.4.4 while 和until 循环···················································································(187) 10.4.5 case 条件选择························································································(189) 10.4.6 无条件控制语句break 和continue·······························································(189) 10.4.7 函数定义······························································································(189) 10.5 命令分组·······································································································(190) 10.6 用trap 命令捕捉信号························································································(190) 10.7 运行shell 程序的方法·······················································································(191) 10.8 bash 程序的调试······························································································(191) 10.9 bash 的内部命令······························································································(192) 第 11 章 文件操作·································································································(194) 11.1 Linux 文件结构·······························································································(194) 11.1.1 Linux 文件系统······················································································(194) 11.1.2 Linux 目录结构······················································································(195) 11.1.3 Linux 文件分类······················································································(197) 11.1.4 常见的文件类型·····················································································(198) 11.1.5 Linux 文件属性······················································································(198) 11.2 系统调用·······································································································(198) 11.3 Linux 文件描述符····························································································(199) 11.4 不带缓存的I/O 操作·························································································(200) 11.4.1 creat 函数·····························································································(200) 11.4.2 open 函数·····························································································(201) 11.4.3 read 函数······························································································(203) 11.4.4 write 函数·····························································································(204) 11.4.5 lseek 函数·····························································································(204) 11.4.6 close 函数·····························································································(205) 11.4.7 经典范例:文件复制···············································································(205) 11.5 带缓存的I/O 操作····························································································(207) 11.5.1 3 种类型的缓冲······················································································(207) 11.5.2 fopen 函数····························································································(209) 11.5.3 fclose 函数····························································································(209) 11.5.4 fdopen 函数···························································································(210) 11.5.5 fread 函数·····························································································(210) 11.5.6 fwrite 函数····························································································(211) 11.5.7 fseek 函数·····························································································(212) 11.5.8 fgetc 函数、getc 函数和getchar 函数···························································(213) 11.5.9 fputc 函数、putc 函数和putchar 函数···························································(214) 11.6 fgets 函数与gets 函数的比较分析········································································(215) 11.7 输出与输入····································································································(217) 11.7.1 printf 函数、fprintf 函数和sprintf 函数·························································(217) 11.7.2 scanf 函数、fcanf 函数和sscanf 函数···························································(220) 第12 章 进程控制编程·····························································································(222) 12.1 为何需要多进程(或者多线程),为何需要并发····················································(222) 12.1.1 进程····································································································(222) 12.1.2 进程分类······························································································(223) 12.1.3 进程的属性···························································································(223) 12.1.4 父进程和子进程·····················································································(223) 12.2 Linux 进程管理·······························································································(224) 12.2.1 ps 监视进程工具·····················································································(224) 12.2.2 pgrep 查询进程工具················································································(226) 12.2.3 终止进程的工具kill、killall、pkill 和xkill····················································(226) 12.2.4 top 监视系统任务的工具··········································································(228) 12.2.5 进程的优先级:nice 和renice ····································································(229) 12.3 Linux 进程的三态····························································································(230) 12.3.1 三种基本状态························································································(230) 12.3.2 三种状态间的转换··················································································(231) 12.4 Linux 进程结构·······························································································(231) 12.5 Linux 进程控制块PCB ······················································································(232) 12.6 Linux 进程调度·······························································································(233) 12.6.1 调度的目标···························································································(233) 12.6.2 调度算法······························································································(233) 12.6.3 优先级反转···························································································(235) 12.7 进程创建·······································································································(236) 12.7.1 获取进程······························································································(236) 12.7.2 启动进程:fork( ) ···················································································(237) 12.7.3 启动进程:vfork( )··················································································(240) 12.7.4 启动进程:exec 族··················································································(241) 12.7.5 启动进程:system···················································································(244) 12.8 进程等待·······································································································(245) 12.8.1 僵尸进程的产生·····················································································(245) 12.8.2 如何避免僵尸进程··················································································(247) 12.8.3 wait 函数和waitpid 函数···········································································(247) 12.9 进程退出·······································································································(251) 12.9.1 退出方式的不同点··················································································(252) 12.9.2 exit 函数和_exit 函数···············································································(252) 12.9.3 exit 函数和_exit 函数的区别······································································(253) 12.10 守护进程······································································································(253) 12.10.1 守护进程概述······················································································(253) 12.10.2 守护进程的创建···················································································(254) 12.10.3 创建守护进程的一般步骤·······································································(254) 12.10.4 利用库函数daemon 创建守护进程····························································(258) 第 13 章 进程间通信方式·························································································(260) 13.1 进程间通信方式概述························································································(260) 13.1.1 进程间通信的目的··················································································(260) 13.1.2 Linux 进程间通信方式简介·······································································(261) 13.2 管道通信·······································································································(262) 13.2.1 创建无名管道························································································(262) 13.2.2 读写无名管道························································································(263) 13.2.3 无名管道应用实例··················································································(267) 13.2.4 创建有名管道························································································(269) 13.2.5 读写有名管道························································································(271) 13.3 管道通信方式的应用场景··················································································(274) 13.4 信号·············································································································(275) 13.4.1 信号及信号来源·····················································································(275) 13.4.2 信号种类······························································································(275) 13.4.3 信号处理方式························································································(277) 13.4.4 信号发送······························································································(277) 13.4.5 自定义信号处理方式···············································································(279) 13.4.6 信号集操作···························································································(284) 13.4.7 使用信号注意事项··················································································(285) 13.5 消息队列·······································································································(287) 13.5.1 消息队列基础理论··················································································(287) 13.5.2 使用消息队列························································································(288) 13.5.3 消息队列API ························································································(289) 13.5.4 消息队列的限制·····················································································(292) 13.5.5 消息队列的应用实例···············································································(292) 13.6 信号灯··········································································································(295) 13.6.1 信号灯概述···························································································(295) 13.6.2 内核实现原理························································································(296) 13.6.3 使用信号灯···························································································(296) 13.6.4 信号灯API ···························································································(297) 13.6.5 信号灯的限制························································································(299) 13.6.6 竞争问题······························································································(299) 13.6.7 信号灯应用实例·····················································································(300) 13.7 共享内存方式一······························································································(303) 13.7.1 内核实现原理························································································(304) 13.7.2 mmap( )及其相关系统调用········································································(304) 13.7.3 mmap( )范例··························································································(306) 13.7.4 对mmap( )返回地址的访问·······································································(310) 13.8 共享内存方式二······························································································(312) 13.8.1 系统V 共享内存原理··············································································(312) 13.8.2 系统V 共享内存API···············································································(314) 13.8.3 系统V 共享内存范例··············································································(314) 第 14 章 多线程编程·························································································(318) 14.1 线程概述···································································································(318) 14.1.1 为什么有了进程的概念后,还要再引入线程呢··············································(318) 14.1.2 多线程的优点························································································(319) 14.1.3 多线程的缺点························································································(319) 14.2 多线程的实现·································································································(320) 14.2.1 线程的创建···························································································(320) 14.2.2 终止线程······························································································(322) 14.2.3 等待线程终止························································································(323) 14.3 线程属性·······································································································(324) 14.3.1 线程属性初始化·····················································································(324) 14.3.2 线程分离······························································································(325) 14.3.3 线程的继承性························································································(326) 14.3.4 线程的调度策略·····················································································(327) 14.3.5 线程的调度参数·····················································································(327) 14.3.6 实例分析······························································································(329) 14.4 线程同步机制·································································································(330) 14.4.1 互斥锁(Mutex) ···················································································(330) 14.4.2 互斥锁使用实例·····················································································(332) 14.4.3 条件变量(Conditions)···········································································(333) 14.4.4 条件变量使用实例··················································································(335) 第 15 章 网络编程································································································(337) 15.1 TCP/IP 协议概述····························································································(337) 15.1.1 TCP/IP 协议的起源·················································································(337) 15.1.2 TCP/IP 协议的特性与应用········································································(338) 15.1.3 互联网地址···························································································(339) 15.1.4 域名系统······························································································(340) 15.1.5 封装····································································································(340) 15.1.6 TCP/IP 协议的工作模型···········································································(341) 15.1.7 TCP/IP 协议层······················································································(342) 15.1.8 TCP/IP 协议的应用·················································································(343) 15.1.9 网桥、路由器和网关···············································································(344) 15.2 TCP 和UDP ····························································································(345) 15.2.1 TCP ····································································································(345) 15.2.2 三次握手······························································································(346) 15.2.3 TCP 数据报头························································································(347) 15.2.4 UDP ····································································································(348) 15.2.5 协议的选择···························································································(348) 15.2.6 端口号和IP 地址····················································································(348) 15.3 套接字····································································································(349) 15.3.1 Socket 的概念························································································(349) 15.3.2 Socket 的类型························································································(349) 15.3.3 Socket 的信息数据结构············································································(349) 15.3.4 数据存储优先顺序的转换·········································································(350) 15.3.5 地址格式转化························································································(351) 15.3.6 名字地址转化························································································(352) 15.4 网络编程··································································································(355) 15.4.1 建立Socket 通信····················································································(355) 15.4.2 绑定地址······························································································(356) 15.4.3 监听····································································································(358) 15.4.4 接受请求······························································································(358) 15.4.5 连接服务器···························································································(359) 15.4.6 发送数据······························································································(360) 15.4.7 接收数据······························································································(362) 15.5 采用TCP 协议的C/S 架构实现·····································································(363) 15.5.1 模块封装······························································································(363) 15.5.2 服务器端的实现·····················································································(365) 15.5.3 客户端的实现························································································(366) 15.6 并发服务器模型························································································(367) 15.6.1 多进程解决方案·····················································································(367) 15.6.2 多线程解决方案·····················································································(368) 15.6.3 调用fcntl 将sockfd 设置为非阻塞模式························································(374) 15.7 多路转接模型······················································.··································(374) 15.7.1 服务器端的实现·····················································································(375) 15.7.2 客户端的实现························································································(379) 15.8 采用UDP 的C/S 架构的实现··············································································(381) 15.8.1 服务器端的实现·····················································································(381) 15.8.2 客户端的实现························································································(382) 15.8.3 UDP 传输文件的实现··············································································(383) 第 16 章 SQLite3 数据库编程··················································································(386) 16.1 SQLite 数据库简介···························································································(386) 16.2 SQLite3 的命令·······························································································(387) 16.3 SQLite 编程接口······························································································(389) 16.3.1 数据库的打开与关闭···············································································(389) 16.3.2 数据库的语句执行··················································································(390) 16.3.3 数据库查询语句操作···············································································(391) 第 17 章 高性能服务器设计······················································································(395) 17.1 select 系统调用································································································(395) 17.1.1 select API······························································································(395) 17.1.2 fd_set···································································································(396) 17.1.3 文件描述符就绪条件···············································································(397) 17.1.4 select 实现TCP 循环服务器案例分析··························································(397) 17.2 poll 系统调用··································································································(400) 17.2.1 poll API································································································(400) 17.2.2 poll 函数的事件标识符·············································································(400) 17.2.3 返回值和错误代码··················································································(401) 17.2.4 poll 实现TCP 循环服务器案例分析·····························································(401) 17.3 epoll 系列系统调用···························································································(404) 17.3.1 select 的缺陷·························································································(404) 17.3.2 内核事件表···························································································(405) 17.3.3 epoll_wait 函数·······················································································(405) 17.3.4 LT 模式和ET 模式·················································································(406) 17.4 xinetd 配置·····································································································(406) 17.4.1 Linux 守护进程······················································································(406) 17.4.2 超级服务xinetd······················································································(407) 17.4.3 xinetd 配置文件······················································································(407) 参考文献·········································································································(409)
你还可能感兴趣
我要评论
|