描述
开 本: 128开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302460572丛书名: 高等院校信息技术规划教材
阅读本书,要求读者具有C语言程序设计与嵌入式系统基础知识。本书可以作为高等院校计算机类、电子信息科学类及物联网工程等专业的本科生或研究生教材,也可以作为嵌入式工程技术人员学习Linux程序设计的参考书.
目录Contents
第1章绪论1
1.1Linux系统简介1
1.1.1早期操作系统的发展1
1.1.2Linux系统的发展过程2
1.1.3Linux的版权2
1.2Linux操作系统特点3
1.2.1Linux系统特性3
1.2.2Linux与其他操作系统的比较5
1.3Linux内核组成7
1.3.1进程管理8
1.3.2内存管理9
1.3.3虚拟文件系统9
1.3.4网络子系统11
1.4Linux在嵌入式系统中的应用12
1.4.1嵌入式Linux系统优势12
1.4.2嵌入式Linux交叉编译过程13
1.4.3嵌入式Linux的不足及改进14
习题16
第2章嵌入式系统概述17
2.1计算机系统发展及分类17
2.1.1计算机的主要应用领域17
2.1.2计算机系统分类20
2.2嵌入式系统简介21
2.2.1嵌入式系统定义21
2.2.2嵌入式系统的分类与特点22
2.2.3嵌入式系统发展历史23◆嵌入式Linux程序设计目录2.2.4嵌入式系统组成24
2.3ARM简介27
2.3.1ARM体系结构特点27
2.3.2ARM系列微处理器28
2.3.3ARM编程模型33
2.4嵌入式操作系统36
2.4.1嵌入式Linux36
2.4.2VxWorks37
2.4.3QNX37
2.4.4Windows CE37
2.4.5Palm OS37
2.5嵌入式系统开发过程38
2.5.1嵌入式系统整体开发过程38
2.5.2嵌入式硬件开发流程41
2.5.3嵌入式软件开发流程43
习题44
第3章Linux系统安装与配置45
3.1Linux系统版本45
3.1.1Linux 内核版本45
3.1.2Linux系统发行版本49
3.2Linux的安装过程51
3.2.1系统最低配置与推荐配置51
3.2.2安装前准备工作51
3.2.3硬盘分区52
3.2.4安装系统52
3.3Linux系统目录结构及基本配置60
3.3.1Linux目录结构60
3.3.2系统启动过程61
3.3.3登录切换64
3.3.4安装程序65
习题67
第4章Linux系统操作基础68
4.1Shell与命令行68
4.1.1Shell概述68
4.1.2Shell命令的分类69
4.1.3Shell命令使用技巧69
4.2文件管理70
4.2.1什么是文件70
4.2.2Linux文件系统70
4.2.3Linux文件系统相关命令71
4.3用户管理82
4.3.1用户类型82
4.3.2用户账号管理83
4.3.3组管理86
4.4网络管理87
4.4.1网络的基本配置87
4.4.2网络状态命令89
4.5进程管理93
4.5.1什么是进程93
4.5.2进程管理命令93
4.5.3进程查看命令95
习题97
第5章Linux系统C语言程序设计98
5.1C语言概述98
5.1.1C语言发展过程98
5.1.2C语言的特点99
5.1.3C语言与Linux系统100
5.2Linux系统C语言程序设计过程102
5.2.1Linux系统C语言程序流程102
5.2.2gcc的编译选项103
5.3GDB调试器用法105
5.3.1gdb使用流程105
5.3.2gdb基本命令109
5.4make工程管理器113
5.4.1makefile基本结构114
5.4.2makefile变量115
5.4.3makefile规则118
5.5模块化程序设计119
5.5.1静态库的实现119
5.5.2动态库的实现121
5.6ARM平台Linux交叉编译环境121
5.6.1源码编译方式122
5.6.2二进制解压安装123
5.7集成开发环境124
5.7.1Qt Creator125
5.7.2KDevelop125
5.7.3Code::Blocks125
5.7.4NetBeans126
5.7.5Eclipse127
习题128
第6章Linux系统移植129
6.1UBoot移植129
6.1.1BootLoader简介129
6.1.2UBoot介绍133
6.1.3UBoot装载过程133
6.1.4OK6410开发板UBoot的移植149
6.2Linux内核移植150
6.2.1计算机处理器架构150
6.2.2Linux内核及源码结构153
6.2.3Linux内核移植155
6.3根文件系统移植163
6.3.1虚拟文件系统164
6.3.2文件系统分类165
6.3.3根文件系统的挂载过程167
6.3.4根文件系统制作170
习题173
第7章Linux并发程序设计174
7.1Linux进程174
7.2进程控制175
7.2.1获取进程ID176
7.2.2创建进程176
7.2.3进程调度179
7.2.4进程终止180
7.2.5等待进程结束181
7.2.6守护进程183
7.3进程之间的通信186
7.3.1管道186
7.3.2信号193
7.3.3消息队列203
7.3.4信号量208
7.3.5共享内存213
7.4线程216
7.4.1创建轻量级进程217
7.4.2POSIX线程218
7.4.3线程属性222
7.4.4线程之间的同步与互斥226
习题237
第8章Linux网络编程238
8.1网络编程的基本知识238
8.2套接字239
8.2.1套接字函数239
8.2.2本地套接字243
8.2.3网络套接字246
8.3TCP程序设计253
8.4UDP程序设计257
8.5套接字属性设置261
习题265
第9章Linux文件编程266
9.1底层文件I/O266
9.1.1文件描述符267
9.1.2底层文件I/O函数267
9.2高级文件操作270
9.2.1文件加锁270
9.2.2多路复用276
9.3标准文件I/O285
9.3.1打开和关闭文件286
9.3.2文件读写288
习题291
第10章Linux设备驱动程序设计292
10.1设备驱动模型简介292
10.1.1底层数据模型292
10.1.2上层设备模型297
10.1.3字符设备驱动模型应用接口302
10.2platform设备驱动程序设计306
10.2.1platform_device注册306
10.2.2platform_driver注册307
10.2.3platform设备驱动框架源码310
10.3设备驱动程序编译及加载313
10.3.1编译Linux设备驱动程序313
10.3.2驱动程序的加载314
10.4设备驱动程序硬件访问317
10.4.1内存与I/O设备317
10.4.2中断320
10.5驱动程序设计实例分析321
10.5.1蜂鸣器驱动程序设计321
10.5.2中断驱动程序333
10.5.3混杂设备驱动程序336
习题339
第11章用户界面程序设计340
11.1Qt简介及安装340
11.1.1Qt简介340
11.1.2Qt安装341
11.2Qt程序设计入门343
11.2.1命令行方式编程343
11.2.2Qt Creator方式345
11.2.3Qt程序的运行机制353
11.3Qt常用类介绍357
11.3.1Qt分组类库357
11.3.2Qt类库介绍359
习题382
前言Foreword
嵌入式系统在功耗、移动性等方面具有传统计算机所不具备的优点,在当前工业控制、物联网以及消费电子等多个领域具有广阔的应用前景,发展潜力巨大。随着嵌入式CPU的性能不断提高,嵌入式系统具有逐渐取代桌面PC的趋势,成为计算机技术发展的新方向。Linux内核支持x86、PowerPC、ARM等主流的CPU架构,移植性能好,内核可以根据需要进行裁减,同时Linux有庞大的用户群,Linux平台应用程序具有统一的开发接口,在系统之间迁移比较容易。基于Linux操作系统平台已成为嵌入式系统开发的主流,越来越多的嵌入式系统开发商在产品中使用Linux系统作为应用平台。随着Linux内核结构以及实时性功能的不断完善,Linux系统在嵌入式领域的应用范围将越来越广。当前,嵌入式Linux程序设计方面的人才缺口巨大。一方面,企业研发嵌入式系统产品需要大量嵌入式软件开发人才;另一方面,由于专业划分及课程本身对知识结构的要求,只有少数高校在相关专业开设了嵌入式Linux程序设计课程,适合高校相关专业课程体系及教学特点的教材也比较缺乏。基于上述背景,本书的编写旨在以C语言程序设计、嵌入式系统程序设计课程为先修课,满足计算机应用、电子信息及物联网工程等专业学时安排的嵌入式Linux程序设计教学的需要。全书共分为11章。第1章绪论介绍Linux的发展过程及版权特点,讲述了Linux操作系统的特点和内核的主要组成部分,嵌入式Linux交叉编译过程以及Linux内核在嵌入式系统应用中的优势、不足及改进途径。第2章嵌入式系统概述介绍了计算机系统功能的演变过程,嵌入式系统在计算机系统分类中所处的位置,嵌入式系统的概念与应用领域、分类及特点,嵌入式系统的组成,ARM体系结构特点及常见的ARM微处理器,ARM的编程模型,常见的嵌入式操作系统以及嵌入式系统的开发过程。第3章Linux系统安装与配置介绍了Linux的内核版本和发行版本、安装过程,Linux系统的启动配置及程序安装方法。第4章Linux系统操作基础介绍了Linux系统的使用和操作,包括文件管理、用户管理以及网络管理等部分。第5章Linux系统C语言程序设计介绍了C语言特点,常用头文件及编译环境变量的配置,C语言程序设计过程,编译器GCC、调试器GDB的用法,工程管理器make的用法,模块化程序设计方法,ARM平台交叉编译环境的搭建以及Linux系统常见的C语言集成开发环境。第6章Linux系统移植介绍了在嵌入式硬件上安装Linux操作系统的过程,分为内核引导程序Bootloader、Linux内核、文件系统等三个部分的移植。第7章Linux并发程序设计介绍了Linux多进程程序设计、进程之间的通信以及多线程程序设计。第8章Linux网络编程介绍了Linux套接字,Linux基于TCP的程序以及Linux基于UDP的程序设计。第9章Linux文件编程介绍了Linux文件的概念,文件的读写操作、文件的加锁访问以及文件的并行访问复用模型等。第10章Linux设备驱动程序设计介绍了设备驱动模型,总线型的设备驱动程序开发、中断设备驱动程序以及混杂型设备驱动程序开发。第11章用户界面程序设计介绍了Qt的安装,Qt应用程序基本结构以及Qt的常用类。本书第4章、第7章、第8章和第9章由张莉莉编写,其余各章由田卫新编写并负责全书统稿。在本书编写过程中,袁军、张富生、鲍灵利、徐昊等提供了帮助,在此表示感谢。由于编者水平有限,书中疏漏之处在所难免,恳请读者批评指正!
作者2016年10月
第5章Linux系统C语言程序设计1.1微型计算机简介C语言是Linux系统开发的主要语言,本章将讲述在Linux系统上用命令行方式编译、调试C语言程序的过程,之后介绍模块化程序设计和项目管理器的使用,最后介绍几种Linux系统的C语言集成开发环境。5.1C语言概述〖*4/5〗5.1.1C语言发展过程C语言是由美国电话电报公司(AT&T)贝尔实验室正式发表的。它的原型是ALGOL 60语言。1963年,剑桥大学将ALGOL 60语言发展成为CPL(Combined Programming Language)。1967年,剑桥大学的Matin Richards 对CPL进行了简化,于是产生了BCPL。1970年,美国贝尔实验室的Ken Thompson将BCPL进行了修改,并为它起名B语言,并且用B语言编写了第一个UNIX操作系统。1973年,美国贝尔实验室的D.M.RITCHIE在B语言的基础上最终设计出了一种新的语言,这就是C语言。1978年,Brian W.Kernighian和Dennis M.Ritchie出版了名著The C Programming Language,从而使C语言成为目前世界上流行最广泛的高级程序设计语言。后来由美国国家标准学会在此基础上制定了一个C语言标准,于1983年发表,通常称之为ANSI C。早期的C语言主要是用于UNIX系统。由于C语言的强大功能和各方面的优点逐渐为人们认识,到了20世纪80年代,C开始进入其他操作系统,并很快在各类大、中、小和微型计算机上得到了广泛的使用,成为当代最优秀的程序设计语言之一。许多早期著名的系统软件,如DBASE Ⅲ PLUS、DBASE Ⅳ、PC|DOS、WORDSTAR等都是由C语言及汇编混合编写的。C语言是一种结构化语言。它层次清晰,便于按模块化方式组织程序,易于调试和维护。C语言的表现能力和处理能力极强。它不仅具有丰富的运算符和数据类型,便于实现各类复杂的数据结构,还可以直接访问内存的物理地址,进行位(bit)一级的操作。由于C语言实现了对硬件的编程操作,因此C语言集高级语言和低级语言的功能于一体,既可用于系统软件的开发,也适合于应用软件的开发。此外,C语言还具有效率高、可移植性强等特点,因此被广泛地移植到了各类各型计算机上,从而形成了多种版本的C语言。目前最流行的C语言版本有Microsoft C(MS C)、Borland Turbo C(Turbo C)和AT&T C。这些C语言版本不仅实现了ANSI C标准,而且在此基础上各自做了一些扩充,使之更加方便、完美。在C的基础上,1983年又由贝尔实验室的Bjarne Stroustrup推出了C 。C 进一步扩充和完善了C语言,成为一种面向对象的程序设计语言。C 的主要版本有Borland C 、Symantec C 和Microsoft Visual C 等。C 提出了一些更为深入的概念,它所支持的这些面向对象的概念容易将问题空间直接地映射到程序空间,为程序员提供了一种与传统结构程序设计不同的思维方式和编程方法。C是C 的基础,C 语言和C语言在很多方面是兼容的。◆嵌入式Linux程序设计第◆5章Linux系统C语言程序设计5.1.2C语言的特点〖*2〗1. 简洁紧凑、灵活方便C语言一共只有32个关键字,9种控制语句,程序书写自由,主要用小写字母表示。它把高级语言的基本结构和语句与低级语言的实用性结合起来。C语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。2. 运算符丰富C的运算符包含的范围很广泛,共有34个运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C的运算类型极其丰富,表达式类型多样化,灵活使用各种运算符可以实现在其他高级语言中难以实现的运算。3. 数据结构丰富C的数据类型有: 整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据类型的运算。并引入了指针概念,使程序效率更高。另外,C语言具有强大的图形功能,支持多种显示器和驱动器,且计算功能、逻辑判断功能强大。4. C是结构式语言结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C语言程序是以函数形式提供给用户的,这些函数可方便地调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。5. C语法限制不太严格、程序设计自由度大一般的高级语言语法检查比较严,能够检查出几乎所有的语法错误。而C语言允许程序编写者有较大的自由度。6. C语言允许直接访问物理地址,可以直接对硬件进行操作C语言既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元,可以用来编写系统软件。7. C语言程序生成代码质量高,程序执行效率高C语言程序一般只比汇编程序生成的目标代码效率低10%~20%。◆嵌入式Linux程序设计第◆5章Linux系统C语言程序设计8. C语言适用范围大,可移植性好 C语言有一个突出的优点就是适合于多种操作系统,如DOS、UNIX,也适用于多种机型。5.1.3C语言与Linux系统C语言和Linux系统结合十分紧密,Linux系统本身是以C语言为主编写的。Linux系统内核提供的函数库、系统调用等都是以C语言原生方式提供,头文件、二进制库文件以及对应的C语言源代码可以很方便找到,为在Linux系统下开发C语言应用程序提供了很大的便利。此外,Linux系统提供了理想的C语言开发环境,包括: (1) 完善的编译环境,包括gcc、as、ld等编译、链接工具;(2) 强大的调试环境,主要是gdb工具;(3) 灵活的项目编译工具,如make工具;(4) 丰富的开源代码库等。1. Linux系统中的C语言头文件Linux系统中头文件放在/usr/include目录下,访问路径在环境变量中定义,说明如下。(1) 常用头文件,存放在/usr/include根目录。a.out头文件,定义了a.out执行文件格式和一些宏。常数符号头文件,目前仅定义了i节点中i_mode字段的各标志位。字符类型头文件,定义了一些有关字符类型判断和转换的宏。错误号头文件,包含系统中各种出错号(Linus从minix中引进的)。文件控制头文件,用于文件及其描述符的操作控制常数符号的定义。信号头文件,定义信号符号常量、信号结构以及信号操作函数原型。基本输入、输出函数头文件。标准参数头文件,以宏的形式定义变量参数列表。标准定义头文件,定义了NULL、offsetof(TYPE,MEMBER)。字符串头文件,主要定义了一些有关字符串操作的嵌入函数。终端输入输出函数头文件,主要定义控制异步通信口的终端接口。时间类型头文件,主要定义了tm结构和一些有关时间的函数原型。Linux标准头文件,定义了各种符号常数和类型,并声明了各种文件操作函数。用户时间头文件,定义了访问和修改时间结构以及utime()原型。(2) 体系结构相关头文件子目录include/asm。这些头文件主要定义了一些与CPU体系结构密切相关的数据结构、宏函数和变量。I/O头文件,以宏的嵌入汇编程序形式定义对I/O端口操作的函数。内存复制头文件,含有memcpy()嵌入式汇编宏函数。段操作头文件,定义了有关段寄存器操作的嵌入式汇编函数。系统头文件,定义了设置或修改描述符/中断门等的嵌入式汇编宏。(3) Linux内核专用头文件子目录include/linux。内核配置头文件,定义键盘语言和硬盘类型(HD_TYPE)可选项。软驱头文件,含有软盘控制器参数的一些定义。文件系统头文件,定义文件表结构(file,buffer_head,m_inode等)。硬盘参数头文件,定义访问硬盘寄存器端口、状态码和分区表等信息。head头文件,定义了段描述符的简单结构和几个选择符常量。内核头文件,含有一些内核常用函数的原型定义。内存管理头文件,含有页面大小定义和一些页面释放函数原型。调度程序头文件,定义了任务结构task_struct、初始任务0的数据,以及一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。系统调用头文件,含有72个系统调用C函数处理程序,以“sys_”开头。tty头文件,定义了有关tty_io、串行通信方面的参数、常数。(4) 系统专用数据结构子目录include/sys。文件状态头文件,含有文件或文件系统状态结构stat{}和常量。定义了进程中运行时间结构tms以及times()函数原型。类型头文件,定义了基本的系统数据类型。系统名称结构头文件。等待调用头文件,定义系统调用wait()和waitpid()及相关常数符号2. 环境变量(1) 头文件路径。Linux系统在编译时,会把/usr/include、/usr/local/include作为默认的头文件路径,如果开发人员在程序设计中需要包含的头文件不在默认的头文件路径,也不在当前项目所在路径,则可以通过设置gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH或OBJC_INCLUDE_PATH来指定头文件目录。(2) 库文件路径。一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行搜索路径设置即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选其一使用。① 在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。例如: export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH② 在/etc/ld.so.conf.d/libc.conf文件中添加库的搜索路径。将可能存放库文件的路径都加入到/etc/ld.so.conf.d/libc.conf中是比较合理的方法,这样就不用每次手动修改环境变量,将库文件的绝对路径直接写进去就可以了。例如: /usr/X11R6/lib/usr/local/lib/opt/lib5.2Linux系统C语言程序设计过程〖*4/5〗5.2.1Linux系统C语言程序流程在PC运行的Linux系统上,以命令方式开发C语言程序的流程如图51所示。图51C语言开发流程图首先用文本编辑器输入源代码,然后调用gcc命令将源代码编译成可执行的二进制文件,编译成功后,可以在文本命令方式下执行生成的文件。不同于Windows系统,可执行程序有特殊的扩展名,Linux系统中文件是否能执行,取决于当前用户是否对该文件具有执行权限,而与文件名及扩展名无关。例1HelloWorld程序#includevoid main(){printf(“Hello World!\n”);return;}
(1) 在用户的Home文件夹下新建文件夹app,新建hello.c文件,用gedit打开后,录入以上源代码。(2) 在命令窗口,进入app文件夹,执行gcc hello.c o hello 命令,如果编译成功,则在app文件夹下可以看到生成的可执行文件hello,否则,根据错误提示,对源代码进行修改后重新编译,直到成功为止。(3) 在文本命令窗口,执行./hello命令,可看到程序运行结果。5.2.2gcc的编译选项gcc是Linux C编译器的核心命令,有超过100个的可用选项,主要包括总体选项、告警和出错选项、优化选项和体系结构相关选项,具体如下。1. 总体选项gcc总体选项说明如表51所示。表51gcc总体选项说明选 项功 能 说 明c只是编译不链接,生成目标文件“.o”S只是编译不汇编,生成汇编代码E只进行预编译,不做其他处理g在可执行程序中包含标准调试信息o file把输出文件输出到file里v打印出编译器内部编译各过程的命令行信息和编译器的版本I 或include dir在头文件的搜索路径列表中添加dir目录L dir在库文件的搜索路径列表中添加dir目录static链接静态库l library链接名为library的库文件2. 告警选项告警选项说明如表52所示。表52gcc告警选项说明选 项功 能 说 明ansi支持符合ANSI标准的C程序,关闭GNU C中某些不兼容ANSI C的特性pedantic允许发出ANSI C标准所列的全部警告信息w关闭所有告警W all允许发出gcc提供的所有有用的报警信息w error把所有的告警信息转化为错误信息,并在告警发生时终止编译过程3. 优化选项gcc可以对代码进行优化,它通过编译选项“|O n”来控制优化代码的生成,其中,n是一个代表优化级别的整数。对于不同版本的gcc来讲,n的取值范围及其对应的优化效果可能并不完全相同,比较典型的范围是从0变化到2或3。不同的优化级别对应不同的优化处理工作。(1) “O 0”禁止编译器进行优化。默认为此项。(2) “O 1”主要进行线程跳转(Thread Jump)和延迟退栈(Deferred Stack Pops)两种优化。使用优化选项“O 2”除了完成所有“O 1”级别的优化之外,同时还要进行一些额外的调整工作,如处理器指令调度等。(3) “O 3”还包括循环展开和其他一些与处理器特性相关的优化工作。虽然优化选项可以加速代码的运行速度,但对于调试而言将是一个很大的挑战。因为代码在经过优化之后,原先在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句也有可能因为循环展开而变得到处都有。所以建议在调试的时候不使用任何优化选项,只有当程序在最终发行的时候才考虑对其进行优化。4. 体系结构选项gcc体系结构选项说明如表53所示。表53gcc体系结构选项说明选项功 能 说 明march=typetype指定当前CPU的架构,针对不同的CPU使用相应的CPU指令。可选择的type有i386、i486、pentium及i686等mtune=type type指定CPU的型号mieeefp使用IEEE标准进行浮点数的比较mnoieeefp不使用IEEE标准进行浮点数的比较msoftfloat输出包含浮点库调用的目标代码mshort把int类型作为16位处理,相当于short intmrtd强行将函数参数个数固定的函数用ret NUM返回,节省调用函数的一条指令m32/64 生成32位/64位机器上的代码这些体系结构相关选项在嵌入式的设计中会有较多的应用,读者需根据不同体系结构将对应的选项进行组合处理。5.3GDB调试器用法调试是所有程序开发必备的手段。Windows系统程序开发工具大多提供集成开发环境,将编辑、调试及运行等功能集中在同一个界面,使用比较方便。Linux系统C语言程序由于是在命令方式下开发的,调试器也一样必须在命令方式下使用。虽然使用界面不够友好,但是调试功能也一样十分强大。5.3.1gdb使用流程调试的目的是解决程序设计中的逻辑错误。如果源代码编译通过,运行得到的结果与预期不一致,这时利用调试工具就可以比较快速地发现问题。进行调试时,gdb调试器输入的是编译后生成的可执行文件,如果编写程序中有语法错误,使用gcc进行语法检查时会报告错误,就不会生成可执行的文件,这种情况下不能使用gdb。gdb调试器可以单步执行、跟踪、查看变量及内存的值等,这些功能依赖于生成的可执行程序中包含的调试信息。在可执行的二进制文件中包含调试信息,会增加程序文件的长度,同时降低程序的执行效率。使用gcc编译时,默认的情况下是不包含调试信息的。为了使用gdb调试器,必须在gcc命令中使用g选项以便在程序文件中包含调试信息。使用调试器修改程序错误后,应使用不带g选项的gcc命令重新编译生成可执行程序后,再进行发布。下面通过一个例子来讲解gdb的使用流程。例2multi.c#includeint multi(int m){int s,i;s=0;for(i=1;i<=m;i )s=s 1/i;return s;}void main(){int i;for(i=1;i<=20;i ){printf(“m=%d,s=%d\n”,i,multi(i));}return;}
在gedit中录入上面的源代码保存退出后,首先使用gcc对multi.c进行编译,注意加上选项“|g”,使得编译出的可执行代码中包含调试信息,否则gdb无法载入该可执行文件。#gcc -g mulit.c -o multi这段程序没有语法错误,利用gcc编译后,可成功生成可执行程序multi,但运行时发现,程序输出和预期结果不一致。源程序由一个子函数multi(m)和主函数main()组成。multi(m)的功能是计算1 12 … 1m的值,主函数通过循环调用multi(m),输出当m分别为1,2直到20时,函数multi(m)的计算结果。但运行程序的输出,无论m的值是多少,multi(m)的结果全为1。接下来,使用gdb调试器来分析查找程序中的错误。#gdb multi注意,gdb进行调试的是可执行文件multi,而不是multi.c源代码。可以看到,出现一段gdb的版本号、使用的库文件等信息后,就进入了由“(gdb)”开头的命令行界面。1. 查看文件在gdb中输入“l”(list)就可以查看所载入文件对应的源码,如下所示。(gdb) l1#include23int multi(int m)4{5int s,i;6s=0;7for(i=1;i<=m;i )8s=s 1/i;9return s;10}(gdb) l1112void main()13{14int i;15for(i=1;i<=20;i )16{17printf(“m=%d,s=%d\n”,i,multi(i)); 18}19return;20}(gdb) lLine number 21 out of range; multi.c has 20 lines.(gdb)gdb列出的源代码中明确地给出了对应的行号,这样可以方便代码的定位。在gdb的命令中可使用缩略形式的命令,如“l”代表“list”,“b”代表“breakpoint”,“p”代表“print”等,读者也可使用“help”命令查看帮助信息。
2. 设置断点设置断点是调试程序中一个非常重要的手段,它可以使程序到一定位置暂停它的运行。暂停后,程序员在该位置处可以方便地查看变量的值、内存情况等,从而找出代码的错误所在。在gdb中设置断点非常简单,只需在“b”后加入对应的行号即可(这是最常用的方式,另外还有其他方式设置断点),如下所示。(gdb) b 8Breakpoint 1 at 0x40053d: file multi.c,line 8.设置断点后,下次在调试器中运行程序时,程序就会在断点处暂停。如本例中,程序将暂停在第8行前。3. 查看断点情况在设置完断点之后,用户可以输入“info b”来查看设置断点情况,在gdb中可以设置多个断点。(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x000000000040053d in multi at multi.c:84. 清除断点当断点不需要时,可以使用“delete n”命令来清除断点,n为断点编号。delete可删除单个断点,也可删除一个断点的集合,这个集合用连续的断点号来描述。(gdb) d 1(gdb) info bNo breakpoints or watchpoints.除使用“delete”外,也可以使用“clear n”命令来清除断点。不同的是,clear后面的n为行号。
评论
还没有评论。