当前位置: 首页 > 工具软件 > GNU bc > 使用案例 >

GNU开发工具的使用方法

乐正浩博
2023-12-01

一、vi编辑器使用方法

1.1 vi编辑器

  • vi是UNIX系统内非常常见的全屏幕文本编辑器,同样Linux系统当然也有。习惯了Windows下的文件处理后,会感到vi非常不好用。vi的意思是Visual,它是一个立即反应的编辑程序,即可以立即看到操作结果。
  • 我们为什么要学习vi呢?(1)所有类Unix系统都会内置vi文本编辑器,而其他的文本编辑器可能不存在;(2)很多软件的编辑接口都会主动调用vi;(3)vi具有具有编程能力,程序简单,速度非常快。
  • vi有两种模式:输入模式和指令模式,输入模式用于输入文字资料,而指令模式用来下达一些编辑文件、存档、推出vi等操作指令

1.2 vi的基本命令

  • (1)进入和离开vi
  • 进入vi的方法为直接在系统提示符下输入“vi <文件名称>”,vi可以打开所需要编译的文档或创建一个新的文件并打开;离开vi的方式为在指令模式下输入“:q”直接退出vi,而输入“:wq”则表示保存后再离开。
  • 注意,如果想从编辑模式切换到指令模式,则按“ESC”键,如果不知道处于什么模式,可以多按几次“ESC”键,如果系统发出哔哔声,则可以确定进入指令模式。
  • (2)输入模式
  • 进入输入模式有好几个指令如下:
  • 新增(append):输入a表示从光标所在位置后面开始新增资料;输入A表示从光标所在行最后面的位置开始新增资料。
  • 插入(insert):输入i表示从光标所在位置前面开始插入资料;输入I表示从所在行第一个非空白字符前面开始插入资料。
  • 开始(open):输入o表示在所在行下方新增一行并进入输入模式;输入O表示在所在行上方新增加一行并进入输入模式。
  • (3)vi文档基本编辑
  • vi文档的基本编辑包括文字的新增、修改、删除,还包括文字区块的搬移、复制等。
  • 注意,编辑是指在指令模式输入进行操作,对文本进行诸如新增、修改、删除等基本编辑操作。
  • 在指令模式下输入以下内容分别表示的含义:
  • x:表示删除光标所在的字符;
  • dd:表示删除光标所在的行;
  • r:表示修改光标所在的单个字符,r后接要修正的单个字符;
  • R:进入取代状态,新增资料会覆盖原来的资料,直至“ESC”回到指令模式终止;
  • s:删除光标所在字符,并进入输入模式;
  • S:删除光标所在行,并进入输入模式;
  • u:表示恢复被删除的资料,类似于windows系统上的“撤销”功能;
  • U:表示恢复光标所在行的所有改变。
  • 习惯了Windows操作系统的用户,文档的输入和编辑都是在输入模式下完成的。而vi用起来看似很麻烦,但是上述的指令在任何UNIX LIKE终端上都可以使用,这就是学习vi的目的之一。
  • 为了便于记忆和查找,下面把vi的输入模式常用的操作命令做成如下几个表格:
  • vi常用输入模式命令:
命令作用
a在光标后输入文本
A在当前行末尾输入文本
i在光标前输入文本
I在当前行开始位置输入文本
o在当前行后面输入新的一行
O在当前前面输入新的一行
  • vi光标移动命令:
命令作用
b移动到当前单词的开始
e移动到当前单词的结尾
w向后移动一个单词或移动一句话
h向前移动一个字符
j向下移动一行
k向上移动一行
l向后移动一个字符
  • vi删除操作命令:
命令作用
x删除光标所在的字符
dw删除光标所在的单词或一句话
d$或D删除光标至行尾的所有字符
dd删除当前行
  • vi改变与替换操作命令:
命令作用
r替换光标所在的字符
R替换字符序列
cw或ce替换一个单词
cb替换光标所在的前一个字符
c$或C替换子光标位置至行尾的所有字符
cc替换当前行
  • vi查询命令:
命令作用
/abc向后查询“abc”
?abc向前查询“abc”
n向后继续查询
N向前继续查询
  • vi拷贝与粘贴命令:
命令作用
/yw将光标所在
y$或Y将光标至行尾的字符拷贝入剪切板
yy将当前行拷贝入剪切板
p将剪切板的内容粘贴到光标后
P将剪切板的内容粘贴到光标前
  • vi文件保存及退出命令:
命令作用
:q退出不保存
:q!强制退出而且不保存
:w保存编辑
:w filename将编辑内容保存到文件filename中
:w! filename将编辑内容强制保存到文件filename中
:wq或:x或ZZ保存并退出

二、makefile的编写

  • 在Linux系统中,make是一个非常重要的编译命令,无论是项目开发还是软件安装,make和make install命令都是经常要用到的。
  • 利用make工具,可以将大型的开发项目分解为多个易于管理的模块make、makefile工具能简明地理清各个源文件之间错综复杂的关系。
  • make工具可以自动完成编译工作,并可以对上次编译修改后的内容进行编译,因此,极大地提高了项目开发效率。

2.1 makefile简介

make工具最主要地功能就是通过makefile文件来描述程序之间地关系并自动给维护编译工作。makefile文件是按照某种语法进行编写,说明如何编译各个源文件并生成可执行文件,并定义源文件之间地依赖关系,下面是一个makefile示意:

edit : main.o kbd.o command.o display.o \
		insert.o search.o files.o utils.o
		cc -o edit main.o kbd.o command.o display.o \
			insert.o search.o files.o utils.o
main.o : main.c defs.h
		cc -c main.c
kbd.o : kbd.c defs.h command.h
		cc -c kbd.c
command.o : command.c defs.h command.h
		cc -c command.c
display.o : display.c defs.h buffer.h
		cc -c display.c
insert.o : insert.c defs.h buffer.h
		cc -c insert.c
search.o : search.c defs.h buffer.h
		cc -c search.c
files.o : files.c defs.h buffer.h command.h
		cc -c files.c
utils.o : utils.c defs.h
		cc -c utils.c
clean :
		rm edit main.o kbd.o command.o display.o \
			insert.o search.o files.o utils.o
  • 上述makefile文件说明如下所示:
  • (1)反斜杠(\)是换行的意思,我们可以将上面的内容保存在名字为“Makefile”或“makefile”的文件中,然后在终端进入该目录输入命令“make”就可以生成执行文件edit;如果要删除执行文件和所有中间目标文件,只要输入“make clean”即可。
  • (2)依赖关系本质上说明了目标(target)文件是由哪些文件生成。在这个makefile中,目标文件(target)包含执行文件edit、中间目标文件(.o文件)、依赖文件(冒号后面的“.c”和“.h”文件)三类。每个“.o”文件都有一组依赖文件,而这些“.o”文件又是执行文件edit的依赖文件。
  • (3)定义好依赖关系后,后续紧跟的一行定义了如何生成目标文件的操作命令,注意一定要以“Tab”键开头。
  • (4)clean不是一个文件,它是一个动作名字,make就不会自动寻找文件的依赖性。
  • 从上面个的例子可以看到,makefile文件作为一种描述文档通常包含三方面内容:(1)宏定义;(2)源文件之间的相互依赖关系;(3)可执行的命令。

2.2 make命令

  • 在make命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些参数指定了需要编译的目标文件,标准形式如下:
  • targeta [target2 …] : [:] [dependent1 …] [;commands] [#…]
  • [(tab) commands] [#…]
  • 方括号中间的部分表示可选项。targets和dependents当中可以包括字符、数字、句点和“/”符号。除了引用,commands中不能含有“#”,也不允许换行。
  • 通常情况下,命令行参数中智能含有一个“:”,此时command序列通常与makefile文件中某些定义文件间依赖关系的描述行有关。如果与目标相关联的那些描述行指定了相关的command序列,那就执行这些相关的command命令。
  • 如果命令行参数中有两个冒号,则此时的command序列可能与makefile中所有描述文件的依赖关系的行有关。此时将执行那些与目标相关联的描述行所指向的命令,同时执行build-in规则。
  • make命令本身可以带有四种参数:标志、宏定义、描述文件名和目标文件名,标准格式如下所示:
  • make [flags] [macro definitions] [targets]
  • UNIX系统下标志位flags选项的含义如下:
  • (1)-f file:指定file文件为描述文件,如果file参数为“-”符号,则描述文件指向标准输入。如果没有“-f”参数,则系统将默认当前目录下名为“makefile”或“Makefile”的文件为描述文件。
  • (2)-i:忽略执行命令返回的出错信息。
  • (3)-s:沉默模式,在执行之前不输出相应的命令行信息。
  • (4)-r:禁止使用build-in规则。
  • (5)-n:非执行模式,输出所有执行命令,但并不执行。
  • (6)-t:更新目标文件。
  • (7)-q:make命令根据目标文件是否更新,返回“0”或非“0”的状态信息。
  • (8)-p:输出所有宏定义和目标文件描述。
  • (9)-d:Debug模式,输出有关文件和检测时间的详细信息。
  • Linux系统下make标志位的常用选项与UNIX系统稍有不同,这里列出不同部分:
  • (1)-c dir:在读取makefile之前改变指定的目录dir。
  • (2)-I dir:当包含其他makefile文件时,利用该选项指定搜索目标。
  • (3)-h:help文档,显示所有的make选项。
  • (4)-w:在处理makefile之前和之后,都显示工作目录。
  • 通过命令行参数中的target,可指定make要编译的目标,而且允许同时定义编译多个目标。如果没有指定目标,则系统默认target指向描述文件中的第一个目标文件。
  • 下面举一个例子,清除编译过程中的中间文件如下所示:
clean:
	rm -f *.o

2.3 隐含规则

  • 在make工具中包含一些内置的隐含规则,这些规则定义了如何从不同的依赖文件建立特定类型的目标,UNIX系统通常支持基于文件扩展名的隐含规则:
.c : .o
	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
  • 系统默认的常用的文件扩展名含义如下所示:
  • (1).o:目标文件;
  • (2).c:C源文件;
  • (3).f:FORTRAN源文件;
  • (4).s:汇编源文件;
  • (5).y:Yacc-C源语法。
  • GNU make除了支持扩展名规则,还支持另一种隐含规则——模式规则。模式规则更常用,它可以定义更加复杂的依赖性规则,它非常类似于正则化,但是在目标名称的前面应该多加一个“%”。同时模式规则还能定义目标文件与依赖文件之间的关系,下面举一个例子,如何采用模式规则如何将任意一个“file.c”文件转换为“file.o”:
%.c : %.o
	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
	#EXAMPLE#
  • 在Linux系统中,大多数软件是提供源代码的,而不是可执行文件,需要用户根据自己的系统进行配置、编译后,才能正常使用软件,因此,只有掌握了make工具,我们才能领略到自由软件Linux系统带来的便利。

三、gcc的使用

  • gcc编译器能够实现从C、C++、Objective-C、汇编语言等源文件向运行在特定CPU硬件上的目标代码的转换。

3.1 gcc的语法及运行原理

  • gcc语法格式如下所示:
  • gcc [ option | filename ] …
  • g++ [option | filename ] …
  • 其中,option表示gcc的操作选项,filename是要处理的文件。
  • 说明:gcc处理C语言,g++处理C++语言,这两个编译器生成新的程序需要四个阶段:预处理、编译、汇编、连接,他们能对输入文件做不同阶段的处理。
  • (1)gcc(GNU Compiler Collection,GNU编译器套件):对预处理过的文件(扩展名为“*.i”)预设为C语言,并在程序连接阶段采用C语言的连接方式处理。
  • (2)g++:对预处理过的文件(扩展名为“*.i”)预设为C++语言,并在程序连接阶段采用C++语言的连接方式处理。
  • 原始程序代码的扩展名表明程序所用的语言和相应的处理方法:
扩展名编程语言处理方法
.cC原始程序预处理、编译、汇编
.C或.cc或.cxxC++原始程序预处理、编译、汇编
.mObjective-C原始程序预处理、编译、汇编
.i经过预处理的C原始程序编译、汇编
.ii经过预处理的C++原始程序编译、汇编
.s组合语言原始程序汇编
.S组合语言原始程序预处理、汇编
.h预处理头文件不常出现在指令行
  • 其他扩展名的文件由连接程序来处理,常用的包括:(1).o:object file;(2).a:archive file。
  • 编译器把编译生成目标代码的任务的四个步骤的任务总结如下:
  • (1)预处理:把预处理命令扫描处理完毕;
  • (2)编译:把预处理后的结果编译成汇编或者目标模块;
  • (3)汇编:把编译出来的结果汇编成具体CPU上的目标代码模块;
  • (4)连接:把多个目标代码模块连接成一个大的目标模块。

3.2 gcc控制选项

  • gcc的运行选项分为12类,他们从12个方面控制着gcc程序的运行,以达到特定的编译目标。
  • 1、全局选项(Overall Options)
  • 全局选项控制gcc的预处理、编译、汇编、连接四个步骤的运行,在缺省的情况下,着4个步骤都要执行。通过给定一些全局选项后,这些步骤都会被选择性执行,而产生一些中间处理文件。
选项作用
-x language对于源文件的编写语言,可通过文件名的扩展名来标示,也可以用这个选项。指定输入文件是用什么语言编写的,language具有以下内容:c、objective-c、c-header、c++、cpp-output、assembler-with-cpp
-x none该选项把上面介绍的-x选项都关掉
-c将源文件编译成目标代码,而不进行连接操作
-S将源文件编译成汇编代码,而不进行连接操作
-E将源文件进行预处理后的结果输出,不做编译、汇编、连接的动作
-o file指明输出文件名为“flie”
-v将整个编译过程的输出信息打印出来
-pipe由于gcc的工作过程分为四步,因此需要临时文件,使用-pipe就是用管道替换临时文件

2、语言相关选项(Language Options)

  • 语言相关控制操作的控制选项主要如下表所示:
选项作用
-ansi表示支持ANSI标准的C程序
-fall-virtual所有可能的成员函数默认为虚函数
-fcond-mismatch允许条件表达式的第二、三个参数的类型不匹配
-fdollars-in-identifiers对于C++语言,允许在标识符(identifier)中使用’ ′ 字 符 ; 禁 止 使 用 ′ '字符;禁止使用' 使'可以使用-fno-dollars-in-identifiers
-fenum-int-equiv对于C++语言,允许int类型到枚举类型的隐式转换;正常情况下,GNU C++允许美剧类型到整形的转换,反之则不允许
-fexternal-templates该选项表示模板实例(template instantiation)全部是外部类型;相应的,如果编译时使用’-fno-external-templates’,则所有模板实例设置为内置
-fno-asm不把asm、inline、typeof作为关键字,而用__asm__, inline, __typeof__替代,‘-ansi’隐含声明了’-fno-asm’
-fno-builtin不接受不是两个下划线开头的内建函数(built-in function),‘-ansi’选项能够阻止alloca和_exit成为成为内建函数
-fno-strict-prototype对于没有参数的函数声明,按照C风格处理,即不说明参数的类型与个数
-fsigned-bitfields如果没有明确声明‘signed’或‘unsigned’修饰符,则该选项定义了有符号域;相应地,-funsinged-bitfields定义无符号域
-fsigned-char把char定义为有符号类型,如同unsigned char;相应地,-funsigned-char把char定义为无符号类型。
-fthis-is-variable对于C++语言,该选项允许对this赋值
-fwritable-strings为了兼容一些老程序,该选项可以把字符串常量存储到可写数据段
-traditional支持传统C编辑器地某些方面,可参考GNU C手册
-traditional-cpp支持传统C预处理器地某些方面内容
-trigraphs支持ANSI C trigraphs

3、预处理相关选项(Preprocessor Options)

  • 预处理选项控制预处理设置,下列选项均针对C预处理器,在正式编译之前对C源文件进行某种处理。需要注意的是这些选项要与‘-E’选项结合使用才有意义,因为它们的输出结果不能进行编译,预处理选项如下表所示:
选项作用
-C通-E结合使用,将预处理的结果的注释保留
-dD设置处理器将所有的宏定义传输到输出端,按照出现的顺序显示
-dM设置处理器输出有效的宏定义列表,通常需要结合‘-E’使用
-dN与‘-dD’类似,但是忽略宏的参量和内容,只在终端输出‘#define name’
-Dmacro定义宏macro,宏的内容定义为字符串‘1’
-Dmacro=defn定义宏macro的内容为defn,命令行上所有的‘-D’选项在‘-U’之前处理
-H除了普通的操作外,gcc显示引用过的头文件名
-idirafter dir将目录dir添加至第二包含路径,如果某头文件主包含路径没有,则预处理器就会检索第二包含路径
-include file在处理常规输入文件之前,首先处理file文件,即先对文件file的内容进行编译;需要注意,命令行上所有‘-D’和‘-U’选项总是在‘-include file’之前处理
-imacros file在处理常规输入文件之前,首先处理文件file,但是忽略输出结果。由于忽略了文件的输出内容,因此该选项的唯一作用就是使得文件file中的宏定义生效,以便用于其他输入文件。在处理该选项之前,需要先处理‘-D’和‘-U’
-iwithprefix dir将目录添加到第二包含路径中,目录名有file和dir合并而成,这里的file由‘-iprefix’选项指定
-iprefix file将file作为‘-iwithprefix’选项的前缀
-M设置预处理器输出一个合适make的规则,用以描述各个目标文件的依赖关系。对于每个源文件,输出与一个make规则,目标文件(target)是源文件对应的目标文件名,依赖文件(dependency)是源文件中‘#include’引用的所有文件。该选项隐含了‘-E’选项
-MD与‘-M’选项相类似,但是把依赖信息输出到文件中,文件名为‘.d’。同时继续指定的编译工作,不像‘-M’选项阻止正常的编译任务。
-MM与‘-M’选项相类似,但是输出结果仅包括用户头文件,例如:“#include file”
-MMD与 `-MD’ 选项类似 , 但是输出结果仅包括用户头文件 , 而不包括系统头文件
-nostdinc不在标准系统目录中检索头文件,只检索‘-I’选项指定的目录。该选项结合‘-I’可以把包含文件检索限制在显式指定的目录
-P将预处理器设置为不产生“#line”命令,需要配合‘-E’选项使用
-Umacro取消宏macro
-undef不预定义任何非标准宏( 包括系统结构标志 )

4、汇编选项(Assembler Options)

选项作用
-Wa,option把选项option传递给汇编器,如果option含有逗号,都在逗号处分割成多个选项

5、连接选项(Linker Options)

  • 连接选项用以编译器进行连接时,连接目标文件。
选项作用
-llibrary连接名为library的库文件,连接器在标准检索目录中查询这个库文件,库文件的名字是‘liblibrary.a’。检索目录除了一些系统标准目录外,还包括用户以‘-L’选项指定的路径。
-I用来指定程序要连接的库,选项后面紧跟的是库名
-nostartfiles不连接系统标准启动文件,并且标准库文件仍然正常使用
-nostdlib不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器
-static在支持动态连接(dynamic linking)的系统上,阻止连接共享库
-shared生成一个共享目标文件,并且生成的目标文件可以与其他目标文件连接生成可执行文件
-symbolic在建立共享目标文件时,把引用绑定到全局符号上,并对所有无法解析的引用作出警告
-Xlinker option把选项option传递给连接器,该选项用来传递系统特定的连接选项
-Wl,option将选项option传递给连接器,如果option具有多个逗号,则在逗号处分割成多个选项
-u symbol取消连接器symbol的符号定义,从而定义连接库模块

6、目录选项(Directory Options)

  • 目录选项用于指定搜索路径,用来查找头文件、库文件和编辑器的成员,相关目录选项如下表所示:
选项作用
-Idir在头文件的检索路径表中添加dir目录
-I-与-I选项相类似。具体应用表述为:(1)可以任何在-I-前面用-I选项指定的搜索路径只适用于 #include “file”,但他们不能用来检索#include 包含的头文件;(2)用-I选项指定的搜索路径位于-I-选项后面,则能够在这些路径中检索所有的#include指令;(3)-I-选项能够阻止当前目录(存放当前输入文件的地方)成为搜索#include "file"的第一选择。
-Ldir在‘-l’选项的检索路径中增加dir目录
-Bprefix该选项指定在哪里查询可执行文件、库文件以及编辑器的数据文件。

7、警告选项(Warning Options)

  • 警告选项是对于程序结构的诊断警告信息:
选项作用
-fsyntax-only诊断程序中的语法错误,而不生成输出信息
-pedantic打开完全遵循ANSI C标准所需的全部警告诊断
-pedantic-errors该选项与‘-pedantic’相似,不同之处在于显示错误而不是警告
-w禁止所有警告信息
-W针对以下事件显示额外的警告信息:(1)在优化编译时,非易变自动变量(nonvolatile automatic variable)可能在调用longjmp时发生改变而发出警告;(2)既可以返回值,也可以不返回值的函数;(3)表达式语句或逗号表达式的左侧没有产生作用(side effect),为了防止这种警告,应该将未使用的表达式前置转换未void类型;(4)无符号数用>或<=和0做比对
-Wall屏蔽‘-W’选项的警告后,在编译后显示所有其他警告信息
-Waggregate-return如果定义或调用了返回结构活联合的函数,编译器就会发出警告
-Wcast-align当某个指针类型强制转换时,导致目标所需的地址对齐增加,编辑器就会发出警告
-Wcast-qual当某个指针类型转换以便移除类型修饰符时,编辑器就会发出警告
-Wchar-subscript警告类型是char的数组下标
-Wcomment如果注释起始符号‘/*’出现在注释中,编译器就会发出警告
-Wconversion如果某函数原形导致的类型转换和无函数原形的类型转换不同,编译器发出警告
-Wenum-clash对于不同枚举类型之间的转换发出警告 ( 仅适用于 C++)
-Werror视警告为错误 ; 出现任何警告即放弃编译

四、库文件管理与使用

4.1 库文件的命名及分类

  • 在Linux系统中,可用的库文件都存放在“/lib”与“/usr/lib”中,库文件名表示为:“lib”+“库名”+“.so或者.a”。
  • Linux系统下的库文件分为两大类:动态链接库(以.so结尾)与静态链接库(以.a结尾)。在默认状况下,gcc在链接时首先首先考虑动态链接库,其次再考虑静态链接库。有时候为了强制使用静态链接库,可以再编译时采用-static选项,例如再“/home/liang/lib”目录下有链接时需要的“libfoo.so”与“libfoo.a”,如下命令可以实现使得gcc再链接时只采用静态链接库:
$ gcc foo.c -L /home/liang/lib/ -static -lfoo -o foo
  • 注意:
  • (1)已经开发的大多数库都采用动态链接库,Linux系统中目前可执行文件的标准格式未ELF格式,且ELF格式的可执行文件更方便于动态链接库的实现。
  • (2)静态链接库再编译连接时,把库文件代码全部加载到可执行文件中,因此生成的文件较大,但是运行时就不再需要库文件了;然而动态链接库在编译连接时,没有将库文件的代码加载到可执行文件中,所以生成文件较小,但是运行时候需要加载文件。

4.2 库文件操作

  • Linux系统常用的库文件操作命令包括ldd与ldconfig:
    1、ldd(Library Dependency Display)
  • ldd的作用是显示一个可执行程序必需使用的共享库,示例如下:
$ ldd /usr/bin/du
linux-vdso.so.1 (0x00007ffd3f5df000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb27bbda000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb27be08000)

2、ldconfig

  • 库文件安装到系统后,为了让动态链接库被系统所识别与共享,就需要运行ldconfig命令。ldconfig的用途主要为在默认检索目录(“/lib”与“/usr/lib”)、动态库配置文件(“/etc/ld.so.conf”)内,检索出可共享的动态链接库,进而创建动态载入程序(ld.so)所需的连接与缓存文件。其中,缓存文件默认为“/etc/ld.so.cache”,次文件保存了已经排好序的动态链接库名称列表,ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,则需要手动运行该命令。
  • 命令格式
  • ldconfig [选项] [libs]
  • 其中,该命令中的选项如下表所示:
选项作用
-v或–verboseldconfig将显示正在扫描的目录、、检索到的动态链接库,以及它所创建的连接的名字
-f CONF指明动态链接库的配置文件为CONF,默认的为“/etc/ld.so.conf”
-C CACHE指明生成的缓存文件为CACHE,默认的为“/etc/ld.so.cache”,该文件存放已经排好序的可共享动态链接库列表
-p或–print-cache设置ldconfig打印出当前缓存文件保存的所有共享库名称
-r ROOT改变应用程序的根目录为ROOT
-nldconfig只扫描命令行指定的目录,不扫描默认目录(/lib、/usr/lib)与配置文件(/etc/ld.so.conf)所列的目录。

4.3 库文件的使用

  • 使用gcc编译器可以把库文件与自主开发的程序链接起来,在“/usr/lib”与“/lib”目录中包含了大部分的动态链接库,在执行连接操作时,首先需要检索这两个目录。有一些库文件可以存放于特定的目录中,在“/etc/ld.conf”配置文件中给出了这些目录的列表,连接程序也会对这些目录进行检索。在对共享库进行安装或更新后,需要执行ldconfig命令“/etc/ld.conf”文件中相对应的项。

五、调试工具的使用

  • 调试Linux内核的工具主要包括kdb、gdb:
  • (1)kdb(Kernel Debug)是SGI公司依据GPL开发的内奸Linux内核调试工具,它只能2.6版内核上调试,并且需要打上补丁,而且是在汇编级层面进行调试,优点是不需要两台机器进行调试;
  • (2)GDB(GNU symbolic debugger)简单地说就是一个调试工具。它是一个受通用公共许可证即GPL保护的自由软件。让程序在你希望的地方停下,此时你可以查看变量、寄存器、内存及堆栈。更进一步你可以修改变量及内存值。GDB是一个功能很强大的调试器,它可以调试多种语言。

5.1 kdb的使用

  • kdb是嵌入到Linux内核中,适用于内核空间程序代码的调试,比如进行设备驱动程序调试、内核模块调试。官方发布的Linux内核并不包含kdb,需要通过修改内核将kdb的源代码嵌入内核中,因此需要重新编译内核。
  • 本文先假设已经安装了kdb,具体安装过程我会在以后的博文中详细介绍。kdb允许进行内存和寄存器修改、应用断点和堆栈跟踪等操作,根据这些操作kdb命令可以分为以下几大类:
  • 1、内存显示与修改命令
  • 常用的内存显示与修改命令包括md、mdr、mm、mmW如下表所示:
命令作用
md以一个地址/符号与行计数器为参数,显示从该地址开始的line-count行的内存
mdr以带有地址/符号与字节计数为参数,显示从指定的址开始的byte-count字节数的初始内存内容。本质上,它与md一样,但是它不显示起始地址,并且不在结尾显示字符转换
mm修改内存内容,它以地址/符号与新内容为参数,以new-contents替换地址处的内容
mmW更改从地址开始的W个字节
  • 2、寄存器显示与修改命令
  • 常用的寄存器显示与修改命令包括rd、rm与ef如下表所示:
命令作用
rd显示处理器寄存器的内容
rm修改寄存器的内容,它以寄存器名称和new-contents作为参数,用new-contents修改寄存器,寄存器的名字因体系结构的不同而不同,目前不能修改控制寄存器
ef以一个地址作为参数,显示指定地址处的异常帧
  • 3、设置断点命令
  • 常用的设置断点命令包括:bp、bc、bd、be与bl如下表所示:
命令作用
bp以一个地址/符号作为参数,在地址处设置断点,当程序遇到该断点时,则停止程序运行,并将控制权交给kdb
bd以断点号作为参数,禁止特殊断点,它只是禁用断点列表中的某个断点,而不是删除该断点
be启用断点
bl列出当前的断点列表
bc从断点列表中删除断点
  • 4、堆栈跟踪命令
  • 常用的堆栈跟踪命令包括:bt、btp、btc与bta:
  • (1)bt命令:选择地将堆栈帧地址作为参数,提供相关当前线程的堆栈信息。
  • (2)btp命令:将进程标识作为参数,对这个进程进行堆栈回溯。
  • (3)bta命令:对处于某种特定状态地所有进程进行回溯操作,如果不带参数则对所有进程进行回溯;也可以通过设置参数选择特定的进程,具体选项参数如下表所示:
选项作用
D不可中断状态
R正在运行
S可中断休眠
T已跟踪或停止
Z僵死
U不可运行

5、其他命令

命令作用
id以一个地址/符号作为参数,对从该地址开始的指令进行反汇编
ss单步执行指令,并将控制返回给kdb
ssb执行从当前指令指针地址开始的指令,直至遇到将引起分支转移的指令为止(典型的分支转移指令有call、return、jump等)
set将环境变量env-var的值设置为value
env显示所有环境变量的值
cpu切换到指定的CPU(尽在SMP结构下有用)
ps显示当前活动的进程,包括pid、父进程pid、CPU号、当前状态以及对应的线程
section列出模块与内核的所有已知的段信息,其中信息段包括段名、段起始地址、段结束地址与段标识
lsmod显示所有模块的信息,包括模块名、模块大小、模块结构地址、引用计数以及被哪个模块所引用
rmmod卸载内核中的模块
go让系统继续运行,知道遇到断点为止
reboot立刻重新引导系统,该命令并没有彻底关闭系统
ll以地址、偏移量与另一个kdb命令作为参数,对链表中每个元素反复执行该kdb命令的操作
help或?显示kdb的命令和简单用法描述

5.2 gdb的使用

1、gdb简介

  • gdb(GNU Debugger)是GNU的调试器,通常与gcc(GNU Compiler Collection)配合使用,使用gdb进行调试时,编译程序需要指定-g或者-ggdb的编译选项如:
gcc -g main.c
gcc -ggdb main.c
  • 其中,-g只产生一般的调试信息;而-ggdb则产生gdb特有的调试信息,且可执行文件的大小会增加很多。
  • gdb是一个程序调试工具,人们可以知道一个正在运行的程序内部发生的事情,利用gdb可以做四类事情来排除错误:(1)启动程序,并显示运行状况;(2)在设置的中断条件下,终止程序运行;(3)检测程序中止时所发生的事情;(4)修改程序文件。
    2、gdb的启动方法及其使用方法
  • 启动gdb的方法如下:
  • (1)gdb <program_1>:其中program_1就是执行文件,通常放在当前目录下。
  • (2)gdb<program_2>core:采用gdb同时调试一个运行程序与core文件,core是程序非法执行后core dump后生成的一个文件。
  • (3)gdb<program_3><PID_1>:如果一个程序是服务程序,该指令可以指定该服务程序的进程ID,gdb会自动地attach上并自动进行调试。
  • gdb的使用方法如下:
gdb [-help] [-nx] [-q] [-batch] [-cd=dir] [-f] [-b bps] 
	[-tty=dev] [-s symfile] [-e prog] [-se prog] [-c core]
	[-x cmds] [-d dir] [prog[core|procID]]

gdb命令的选项说明如下表所示:

gdb命令选项作用
-help列出所有选项,并附带简单的解释
-nx不执行来自任何“.gdbinit”类初始化文件的命令
-q及你只显示介绍和版权信息,批处理模式同样禁止
-batch在批处理模式下运行
-cd=dir用指定目录(dir)名作为运行gdb时的工作目录以替代当前目录
-f通过设置该选项来运行gdb子进程,它告诉gdb在每次显示堆栈帧时以一个可识别的标准形式输出完整的文件名、行号
-b bps在远程调试程序的状态下设置串口的比特率和波特率
-tty=dev采用指定的设备(dev)作为程序的标准输入和输出
-s symfile从文件(symfile)中读取符号表
-e prog用文件(prog)作为一个可执行文件运行,来检测与core转储文件连接的纯数据
-c core指定文件(core)来作为core转储文件来检测
-x cmds执行来自指定文件(cmds)的gdb命令
-d dir在检索源文件的路径中加入指定目录(dir)
  • 下面再介绍gdb将会用到的一些命令如下表所示:
命令作用
f(ile)指定一个可执行文件进行调试,gdb读取这些文件的调试信息
l(ist)列出程序源文件
r(un)装载完要调试的可执行文件后,用rum命令运行可执行文件
b(reak)设置断点
c(ontinue)c命令可以令中断的程序继续执行,知道下一个中断或者程序结束
p(rint)输入某个变量的值
n(ext)程序执行到断点时中断执行,可用n指令单步执行
s(tep)程序执行到断点时中断执行,可用s指令单步执行到某一函数
q(uit)退出gdb
 类似资料: