章嵌入式LinuxC语言开发工具(1)
1.1嵌入式LinuxC语言开发概述(1)
1.2嵌入式LinuxC开发环境(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.2gcc命令常用选项和工作流程(6)
1.4.3库的使用(10)
1.5嵌入式调试器(12)
1.6工程管理器(15)
1.6.1Makefile(16)
1.6.2Makefile特性介绍(18)
1.7Eclipse程序开发(27)
1.7.1Eclipse环境安装(27)
1.7.2EclipseC程序开发(29)
1.8软件版本管理(34)
1.8.1Git版本管理(34)
1.8.2Ubuntu软件包管理(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.6static与extern(57)
2.6.1static(57)
2.6.2extern..(59)
2.7const(60)
2.8auto(61)
2.9register(62)
2.10volatile(63)
2.11typedef详解(64)
2.11.1typedef与结构的问题(64)
2.11.2typedef与#define的问题(66)
2.11.3typedef与#define的另一例(67)
2.11.4typedef与复杂的变量声明(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.5C语言性能优化:使用位操作(79)
第4章语句(81)
4.1空语句(81)
4.2基础语句(82)
4.2.1表达式语句(82)
4.2.2函数调用语句(82)
4.3if语句(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.1do-while语句(86)
4.5.2for语句(86)
4.5.3循环语句的效率(88)
4.6break和continue(89)
4.6.1break语句(89)
4.6.2continue语句(90)
4.7switch语句(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.7array_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.1NULL总是被定义为0吗(110)
5.6.2NULL总是等于0吗(110)
5.6.3空指针的使用(111)
5.7void指针:万能指针(113)
5.8指针数组与数组指针(114)
5.9字符串函数详解(114)
5.10函数指针与指针函数(119)
5.11复杂指针声明:“int*(*(*fp1)(int))[10];”(120)
5.11.1基础(120)
5.11.2const修饰符(121)
5.11.3typedef的妙用(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)
0章shell编程(181)
10.1什么是shell(181)
10.2几种流行的shell(181)
10.3shell程序设计(基础部分)(182)
10.3.1shell的基本语法(182)
10.3.2shell程序的变量和参数(183)
10.4shell程序设计的流程控制(185)
10.4.1test命令(185)
10.4.2if条件语句(186)
10.4.3for循环(187)
10.4.4while和until循环(187)
10.4.5case条件选择(189)
10.4.6无条件控制语句break和continue(189)
10.4.7函数定义(189)
10.5命令分组(190)
10.6用trap命令捕捉信号(190)
10.7运行shell程序的方法(191)
10.8bash程序的调试(191)
10.9bash的内部命令(192)
1章文件操作(194)
11.1Linux文件结构(194)
11.1.1Linux文件系统(194)
11.1.2Linux目录结构(195)
11.1.3Linux文件分类(197)
11.1.4常见的文件类型(198)
11.1.5Linux文件属性(198)
11.2系统调用(198)
11.3Linux文件描述符(199)
11.4不带缓存的I/O操作(200)
11.4.1creat函数(200)
11.4.2open函数(201)
11.4.3read函数(203)
11.4.4write函数(204)
11.4.5lseek函数(204)
11.4.6close函数(205)
11.4.7经典范例:文件复制(205)
11.5带缓存的I/O操作(207)
11.5.13种类型的缓冲(207)
11.5.2fopen函数(209)
11.5.3fclose函数(209)
11.5.4fdopen函数(210)
11.5.5fread函数(210)
11.5.6fwrite函数(211)
11.5.7fseek函数(212)
11.5.8fgetc函数、getc函数和getchar函数(213)
11.5.9fputc函数、putc函数和putchar函数(214)
11.6fgets函数与gets函数的比较分析(215)
11.7输出与输入(217)
11.7.1printf函数、fprintf函数和sprintf函数(217)
11.7.2scanf函数、fcanf函数和sscanf函数(220)
2章进程控制编程(222)
12.1为何需要多进程(或者多线程),为何需要并发(222)
12.1.1进程(222)
12.1.2进程分类(223)
12.1.3进程的属性(223)
12.1.4父进程和子进程(223)
12.2Linux进程管理(224)
12.2.1ps监视进程工具(224)
12.2.2pgrep查询进程工具(226)
12.2.3终止进程的工具kill、killall、pkill和xkill(226)
12.2.4top监视系统任务的工具(228)
12.2.5进程的优先级:nice和renice(229)
12.3Linux进程的三态(230)
12.3.1三种基本状态(230)
12.3.2三种状态间的转换(231)
12.4Linux进程结构(231)
12.5Linux进程控制块PCB(232)
12.6Linux进程调度(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.3wait函数和waitpid函数(247)
12.9进程退出(251)
12.9.1退出方式的不同点(252)
12.9.2exit函数和_exit函数(252)
12.9.3exit函数和_exit函数的区别(253)
12.10守护进程(253)
12.10.1守护进程概述(253)
12.10.2守护进程的创建(254)
12.10.3创建守护进程的一般步骤(254)
12.10.4利用库函数daemon创建守护进程(258)
3章进程间通信方式(260)
13.1进程间通信方式概述(260)
13.1.1进程间通信的目的(260)
13.1.2Linux进程间通信方式简介(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.2mmap()及其相关系统调用(304)
13.7.3mmap()范例(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)
4章多线程编程(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)
5章网络编程(337)
15.1TCP/IP协议概述(337)
15.1.1TCP/IP协议的起源(337)
15.1.2TCP/IP协议的特性与应用(338)
15.1.3互联网地址(339)
15.1.4域名系统(340)
15.1.5封装(340)
15.1.6TCP/IP协议的工作模型(341)
15.1.7TCP/IP协议层(342)
15.1.8TCP/IP协议的应用(343)
15.1.9网桥、路由器和网关(344)
15.2TCP和UDP(345)
15.2.1TCP(345)
15.2.2三次握手(346)
15.2.3TCP数据报头(347)
15.2.4UDP(348)
15.2.5协议的选择(348)
15.2.6端口号和IP地址(348)
15.3套接字(349)
15.3.1Socket的概念(349)
15.3.2Socket的类型(349)
15.3.3Socket的信息数据结构(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.3UDP传输文件的实现(383)
6章SQLite3数据库编程(386)
16.1SQLite数据库简介(386)
16.2SQLite3的命令(387)
16.3SQLite编程接口(389)
16.3.1数据库的打开与关闭(389)
16.3.2数据库的语句执行(390)
16.3.3数据库查询语句操作(391)
7章高性能服务器设计(395)
17.1select系统调用(395)
17.1.1selectAPI(395)
17.1.2fd_set(396)
17.1.3文件描述符就绪条件(397)
17.1.4select实现TCP循环服务器案例分析(397)
17.2poll系统调用(400)
17.2.1pollAPI(400)
17.2.2poll函数的事件标识符(400)
17.2.3返回值和错误代码(401)
17.2.4poll实现TCP循环服务器案例分析(401)
17.3epoll系列系统调用(404)
17.3.1select的缺陷(404)
17.3.2内核事件表(405)
17.3.3epoll_wait函数(405)
17.3.4LT模式和ET模式(406)
17.4xinetd配置(406)
17.4.1Linux守护进程(406)
17.4.2超级服务xinetd(407)
17.4.3xinetd配置文件(407)
参考文献(409)