商品详情
定价:78.0
ISBN:9787121373404
作者:梁庚
版次:第1版
出版时间:2019-09
内容提要:
本书从嵌入式开发角度出发,以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)
- 电子工业出版社有限公司
- 电子工业出版社有限公司有赞官方供货商,为客户提供一流的知识产品及服务。
- 扫描二维码,访问我们的微信店铺