550 likes | 713 Views
第 7 章 嵌入式 Linux 开发环境. 第 7 章 嵌入式 Linux 开发环境. 7.1 GNU Tools 7.2 项目管理 7.3 调试器 7.4 Linux 常用命令. 7.1 GNU Tools. GNU Tools 综述 GCC 编译与链接 GCC 工具介绍 C 语言库 ELF 文件格式. GNU Tools 综述.
E N D
第7章 嵌入式Linux开发环境 • 7.1 GNU Tools • 7.2 项目管理 • 7.3 调试器 • 7.4 Linux常用命令
7.1 GNU Tools • GNU Tools综述 • GCC 编译与链接 • GCC 工具介绍 • C语言库 • ELF文件格式
GNU Tools综述 GNU Tools是Linux环境下的开发工具,用于代码的生成。GNU Tools的重要组成部分是GCC。GCC 是GNU Compiler Collection 的缩写,是一个非常优秀的跨平台编译器集合,支持x86、ARM、MIPS 和PowerPC 等多种目标平台,支持C、C++、Java、ADA、Fortran 和Pascal 等多种高级语言。
GNU Tools综述 gcc和g++分别是GCC中C语言编译器和C++语言编译器,在执行编译工作时,可以分成四步: 预处理:生成.i的文件(预处理器cpp) 编译:将预处理后的文件转换成汇编语言,生成文件.s(编译器gcc) 汇编:生成目标文件.o(汇编器as) 链接:各文件的目标文件生成可执行文件(链接器ld)
GNU Tools综述 • 预处理 • 编译 • 汇编 • 链接
gcc规则 • gcc则通过后缀来区别输入文件的类别,gcc所遵循的部分约定规则如下: • .c为后缀的文件,C语言源代码文件; • .a为后缀的文件,是由目标文件构成的档案库文件; • .cc或.cxx为后缀的文件,是C++源代码文件; • .h为后缀的文件,是程序所包含的头文件; • .o为后缀的文件,是编译后的目标文件; • .s为后缀的文件,是汇编语言源代码文件;
gcc用法 gcc最基本的用法是∶ gcc [options] [filenames] 其中options就是编译器所需要的参数,filenames给出相关的文件名称。 举例: gcc –c main.c gcc –c subr.c gcc –I/usr/include –o prog main.o subr.o
gcc 参数说明 -c 只编译并生成目标文件。 -o FILE 生成指定的输出文件FILE,没有指定FILE,默认输出文件为a.out。 -O 优化生成代码。 -w 不生成任何警告信息。 -Wall 生成所有警告信息。 -g 生成调试信息。GNU 调试器可利用该信息。 -lLIBRARY 连接时搜索指定的函数库LIBRARY。
GCC 编译与链接 /* hello.c */ #include <stdio.h> int main(void) { printf ("Hello world!\n" ); return 0; } 分布完成: 一步完成: 预处理 # gcc -E hello.c -o hello.i 编译和汇编 # gcc -c hello.i -o hello.o 链接 # gcc hello.o -o hello # gcc hello.c -o hello # ./hello Hello world!
GCC 编译与链接 源程序: foo1.c foo2.c 一步完成: # gcc foo1.c foo2.c -o foo 多步完成: # gcc -c foo1.c -o foo1.o # gcc -c foo2.c -o foo2.o # gcc foo1.o foo2.o -o foo
GCC 编译器 GCC 是一个强大的C语言工具集合,它包含了预处理器、编译器、汇编器、链接器等组件。它在需要的时候调用其他的组件(预处理器、编译器、汇编器、链接器)。输入文件的类型和传递给GCC的参数决定了GCC调用具体的哪些组件。 例如对于一个简单的test.c文件,可以使用GCC命令直接将其生成一个可执行文件: # gcc test. c
链接器ld ld程序的作用是把各种目标文件和库文件链接在一起,并定位数据和函数的地址,最终生成执行程序。 ld的一个简单使用例子如下: # ld -o hello/lib/crt0. o hello. o -lc
归档工具ar ar 工具用于建立、修改、提取归档文件(archive)。一个归档文件是包含多个文件的单个文件(也可以把它认为是一个库文件),其结构保证了可以从中检索并得到原始的被包含文件(称做此归档文件的成员)。被包含的原始文件的内容、模式(权限)、时间戳、所有者和组等属性都保存在归档文件中,并且可在提取后,恢复原始文件的相关属性。 ar [-] p[ mod [ relpos]] archive [ member ...]
以下是一个简单的例子,编写两个源程序文件add.c和minus.c。以下是一个简单的例子,编写两个源程序文件add.c和minus.c。 add.c minus. c int add(int a, int b) int minus(int a, int b) { { int result; int result; result = a+b; resresult= a - b; return result; return result; } } 执行命令 # gcc –c add. c minus. c 输入以下命令: # ar rv libtest. a add. o minus. o
移除符号工具strip strip工具用于去除文件中的符号。使用strip既可以移除目标中文件中的某个符号,也可以移除整个节。使用strip,至少要有一个输入文件,也可以输入一个文件列表。 strip [-F bfdname |--target=bfdname ] [-I bfdname |--input-target=bfdname ] [-O bfdname |--output-target=bfdname ] [-s|--strip-all] [-S|-g|-d|--strip-debug] [-K symbolname |--keep-symbol=symbolname ] [-N symbolname |--strip-symbol=symbolname ] [-x|--discard-all ] [-X |--discard-locals] [-R sectionname |--remove-section=sectionname ] [-o file ] [-p|--preserve-dates] [-v |--verbose] [-V|--version] [--help] objfile...
列出文件符号工具nm nm工具的功能是列出目标文件中的符号,这样可以帮助程序员分析可执行程序,获得目标文件中的符号信息和它的属性。 nm [ -a | --debug-syms ] [ -g | --extern-only ] [ -B ] [ -C | --demangle ] [ -D | --dynamic ] [ -s | --print-armap ] [ -A | -o | --print-file-name ] [ -n | -v | --numeric-sort ] [ -p | --no-sort ] [ -r | --reverse-sort ] [ --size-sort ] [ -u | --undefined-only ] [-t radix | --radix= radix ] [ -P | --portability ] [ --target= bfdname ] [-f format | --format= format ] [ --defined-only ] [ -l | --line-numbers ] [ --no-demangle ] [ -V | --version ] [ --help ] [ object-file ...]
以下继续介绍简单的例子,按照刚才介绍ar命令时的例子,执行如下命令:以下继续介绍简单的例子,按照刚才介绍ar命令时的例子,执行如下命令: #include < stdio. h> Int main( int argc, charr * argv[ ] ) { int a=8; int b =3; printf( “a= % d\tb = %d\n”, a, b); int sum= add(a, b); printf( “a + b=%d\n”, sum) ; int cha=minus(a, b); printf( “a – b=% d\n”, cha) ; retum 0; } # nm test.o 输出结果如下: test.c U add 00000000 T main U minus U printf
目标文件复制工具objcopy objcopy工具用来把某种格式的目标文件内容进行转换,并输出为另一种格式的目标文件。objcopy使用GNU BFD库读写目标文件,通过这个BFD库,objcopy能够以一种不同于源目标文件的格式来生成目标文件。 objcopy [ -F bfdname | --target= bfdname ][ -I bfdname | --input-target=bfdname ] [ -O bfdname | --output-target= bfdname ][ -S | --strip-all ] [ -g | --strip-debug ] [ -K symbolname | --keep-symbol= symbolname ][ -N symbolname | --strip-symbol= symbolname ] [ -L symbolname | --localize-symbol= symbolname ][ -W symbolname | --weaken-symbol= symbolname ] [ -x | --discard-all ] [ -X | --discard-locals ][ -b byte | --byte= byte ] [ -i interleave | --interleave= interleave ][ -R sectionname | --remove-section= sectionname ] [ -p | --preserve-dates ] [ --debugging ][ --gap-fill= val ] [ --pad-to= address ] [ --set-start= val ] [ --adjust-start= incr ][ --change-address= incr ] [ --change-section-address= section{=,+,-} val ][ --change-warnings ] [ --no-change-warnings ] [ --set-section-flags= section= flags ][ --add-section= sectionname= filename ] [ --change-leading char ] [--remove-leading-char ][ --weaken ] [ -v | --verbose ] [ -V | --version ] [ --help ]input-file [ outfile]
下面介绍使用objcopy的例子。对于前面生成的可执行文件test,输入如下命令:下面介绍使用objcopy的例子。对于前面生成的可执行文件test,输入如下命令: # file test 输出结果如下所示: Test: ELF 32-bit LSB executable, Intel 80386, version 1 ( SYSV) , for GNU/Linux 2. 2. 5, dynamically linked ( uses shared libs) , not stripped. 输入如下命令: # objcopy-O srec test ts 输人命令: # file ts 输出结果为: Ts: Motorola S-Record; binary data in text format
目标文件信息工具objdump objdump 工具用于显示一个或多个目标文件的信息。由其选项来控制显示哪些特定的信息。 objdump [ -a | --archive-headers ] [ -b bfdname | --target= bfdname ] [ --debugging ] [ -C | --demangle ] [ -d | --disassemble ][ -D | --disassemble-all ] [ --disassemble-zeroes ] [ -EB | -EL | --endian={big | little } ][ -f | --file-headers ] [ -h | --section-headers | --headers ] [ -i | --info ][ -j section | --section= section ] [ -l | --line-numbers ] [ -S | --source ][ -m machine | --architecture= machine ] [ -p | --private-headers][ -r | --reloc ] [ -R | --dynamic-reloc ] [ -s | --full-contents ] [ --stabs ][ -t | --syms ] [ -T | --dynamic-syms ] [ -x | --all-headers ] [ -w | --wide ] [ --start-address= address ] [ --stop-address= address ] [ --prefix-addresses] [ --[no]show-raw-insn ] [ --adjust-vma= offset ] [ --version ] [ --help ] [ object-file...]
C语言库 在嵌入式程序的C语言程序的开发中,C语言库是应用程序所依赖的基础。在C语言库中,提供一些C语言中程序运行的基础,包括标准的库函数,如:printf、malloc、字符串处理等基本函数操作。
在Linux系统中,C语言的运行库也是一组程序,它也依赖于Linux内核,同时所有C语言应用程序则需要依赖C语言的运行库。实际上,C语言的运行库在操作系统的基础上为C语言提供了运行基础。 常用C函数库包括以下几种版本: glibc:是桌面Linux系统中使用的C函数库。 μClibc:来自于μClinux项目,体积小。 newlib:与lLClibc的定位类似,由RedHat发布。
ELF文件格式 • ELF(Executable and Linking Format,可执行链接格式)是UNIX系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,ABI)而开发和发布的。工具接口标准委员会(TIS)选择了正在发展中的ELF标准作为工作在32位INTEL体系上不同操作系统之间可移植的二进制文件格式。在Linux下开发程序可以使用ELF格式作为可执行文件以及程序生成过程的中间文件。 • ELF文件格式包括三种主要的类型: • 可执行文件 • 可重定向文件(*.o) • 共享库(*.so)
ELF文件格式 ELF文件从链接器(linker)的角度看,是一些节(sections)的集合;从程序装载器(loader)的角度看,它是一些段(segments)的集合。 ELF格式的程序和共享库具有相同的结构,只是段的集合和节的集合上有些不同。
7.2项目管理 • 工程管理工具Make与Makefile Make和Makefile提供了一种非常简单有效的工程管理方式。使用这种方式管理工程的原理很简单:Makefile是一个决定怎样编译工程的文本文件,按照一定的规则书写。在工程更新的时候,使用GNU的make工具根据当前的Makefile进行工程编译。
Makefile里主要包含5个方面的内容:显式规则、隐式规则、变量定义、文件指示和注释,如表7-3所示。 注意: 在Makefile中的命令,必须要以<Tab >键开始。这和C语言的等代码源文件有较大差别,在C语言源文件中空格、Tab都是可以忽略的,但是在Makefile中不可以忽略。
GNU make程序具有的使用形式为: make[选项][变量定义][目标] make的选项指出make的工作方式,如表7-4所示。
工程管理工具Make与Makefile /* main.c */ #include "hello.h" int main (int argc,char* argv[]) { hello(argc,argv); return 0; } /* hello.c */ #include <stdio.h> int hello(int argc,char* argv[]) { int i; printf ("Hello world!\n"); for(i = 0;i < argc; i++) printf("argv[%d] = %s\n",i,argv[i]); return 0; } /* hello.h */ int hello(int argc,char* argv[]);
工程管理工具Make与Makefile # Makefile CC := gcc HEAD := hello.h SRC := hello.c main.c OBJS := hello.o main.o TT := hello INC = . CFLAGS = -pipe -w -I$(INC) LDFLAGS = -Wall all:$(TT) $(TT):$(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o $@ %.o:%c $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f *.o $(TT)
工程管理工具Make与Makefile # make gcc -pipe -w -I. -c -o hello.o hello.c gcc -pipe -w -I. -c -o main.o main.c gcc -Wall hello.o main.o -o hello # make clean rm -f *.o hello
版本控制 CVS是一种广泛应用的、开源的、透明于网络 、程序代码版本的分合控制。明于网络的版本控制系统。CVS支持程序代码版本的储存与维护、程序代码版本的追踪回溯、支持多人合作开发项目等。不过这个广为使用的版本控制工具还有不少问题,包括中文支持和二进制文件的处理都有或多或少的问题。SVN的出现改变了这一现状。 SVN保留大多数CVS 特性,而且进一步支持更多的特性,包括版本化管理目录、重命名和文件meta-data、提交是真实的原子操作、可以通过WebDAV/DeltaV协议进行访问、可以选择独立服务器模式、分支和标签是代价低廉(固定不变的)的操作、高效处理二进制文件等。
7.3 调试器 • GDB调试基础 • 远程GDB调试
GDB调试基础 GDB是一个强大的命令行调试工具。命令行的强大就是在于其可以形成执行序列,形成脚本。UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能。 一般来说,GDB主要提供四个方面的功能: 1)启动的程序,可以按照自定义的要求随心所欲地运行程序。 2)可让被调试的程序在指定的设置断点处停住(断点可以是条件表达式)。 3)当程序被停住时,可以检查这时程序中所发生的事。 4)动态的改变程序的执行环境。 调试方法: # gdb hello 使用gdb启动被调试的程序。
GDB调试基础 GDB调试主要使用的语法为: break 在程序中设置端点 clear 清除所有的已定义的停止点。 info 显示相关的信息,如地址、寄存器、栈信息、输入参数等 next 执行下一行,但是不进入函数,相当于step over step 执行下一行,进入函数,相当于step in run 执行当前调试的程序,可以加参数 quit 退出GDB
远程GDB调试 在远程GDB调试的中,调试器是运行在主机的应用程序, 被调试的程序是运行在target上。使用插桩(stub)在目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试。 调试器与被调程序的通信:GDB和调试stub通过GDB串行协议进行通信。指定通信端口(串口、并口和网卡)遵循远程调试协议进行通信。GDB串行协议是一种基于消息的ASCII码协议,包含了诸如读写内存、查询寄存器、运行程序等命令。
7.4 Linux开发基础 Linux常用命令介绍 Linux系统下的vi编辑器 基于Linux的应用程序的开发步骤
Linux常用命令介绍 嵌入式系统开发的实验基础 1.帮助命令 在所有命令中帮助命令是最有用的命令之一。在Linux中要了解一个命令的用法,可以通过man页面查看命令的详细说明。 2.进入与退出Linux系统 进入Linux系统时,必须要输入用户的账号,在系统安装过程中可以建立两种账号,即root和普通用户。root是超级用户账号,通常由系统管理员使用,使用这个账号可以在系统中做任何事情。使用普通用户账号可以进行有限的操作。当用户正确输入用户名和口令后,就能合法地进入系统。屏幕将显示: [root@loclhost/root]# 3.文件操作的常用命令 (1)cp命令 语法:cp [option]〈source〉〈target〉 功能:将文件或目录source复制为target文件或目录。 说明:option选项的含义如下。 ● –f:复制时删除已经存在的目录文件而不提示;
Linux常用命令介绍 嵌入式系统开发的实验基础 ● -i:在覆盖目标文件前,将给出提示要求用户确认,回答“y”时目标文件将被覆盖; ● -p:此时cp除复制源文件的内容外,还将把其修改的时间和访问权限也复制到新文件中; ● -r:若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件,此时目标文件必须是一个目录名。 (2)rm命令 语法:rm [option] dir 功能:删除一个目录中的一个或多个文件或目录。 说明:option选项的含义如下。 ● -f:忽略不存在的文件,不给出提示; ● -r:将参数中列出的全部目录和子目录递归地删除,若没有该选项,rm命令不会删除目录; ● -i:进行交互式删除,以免误操作。 例如:rm -rf dir删除当前目录下名为dir的整个目录(包括下面的文件和子目录)。
Linux常用命令介绍 嵌入式系统开发的实验基础 4.目录操作的常用命令 (1)ls命令 语法:ls [option] dir/file 功能:显示当前目录文件列表。 说明:option选项的含义如下。 ● -a:显示指定目录下所有子目录与文件,包括隐藏文件; ● -c:按文件的修改时间排序。 (2)cd命令 语法:cd directory 功能:改变工作目录。 例如:cd /切换到根目录 cd ..切换到到上一级目录 cd /mnt切换到根目录下的mnt目录
Linux常用命令介绍 嵌入式系统开发的实验基础 (3)pwd命令 语法:pwd 功能:显示当前工作目录的绝对路径。 (4)mkdir命令 语法:mkdir dirname 功能:创建一个名为dirname的目录。 (5)rmdir命令 语法:rmdir dirname 功能:删除一个名为dirname的空目录。 (6)网络配置的相关命令 ifconfig eth0 192.168.0.115设置网卡0的地址为192.168.0.115 ping 192.168.0.83 测试与192.168.0.83的连接是否正常
Linux常用命令介绍 嵌入式系统开发的实验基础 5.磁盘管理命令 (1)mount命令 语法:mount [-t vfstype] [-o option] device dir 功能:在Linux系统下挂载设备。 说明:各选项的含义如下。 ● -t vfstype:指定文件系统的类型,如Linux文件网络共享类型为nfs。常用的类型还有; 光盘或光盘映像:iso9660; DOS fat16文档系统:msdos; Windows 9x fat32文档系统:vfat; Windows NT ntfs文档系统:ntfs; Mount Windows文档网络共享:smbfs。
Linux常用命令介绍 嵌入式系统开发的实验基础 ● -o option:用于描述设备或档案的挂载方式。 -ro:采用只读方式挂载设备; -rw:采用读/写方式挂载设备。 ● device:要挂载的设备。 ● dir:设备在系统上的挂载点。 (2)umount命令 语法:umount dir 功能:卸载已经挂载的设备。 说明:dir表示设备在系统上的挂载点。
Linux常用命令介绍 嵌入式系统开发的实验基础 6.其他命令 (1)insmod命令 语法:insmod [-fkmpsvxX][-o <模块名称>][模块文件][符号名称=符号值] 功能:加载驱动模块。 说明:Linux有许多功能是模块化设计的,在需要时才载入kernel。这样可使kernel较为精简,进而提高效率。这类可载入的模块,通常是设备驱动程序。 (2)rmmod命令 语法:rmmod [-as][模块名称...] 功能:卸载驱动模块。 说明:执行rmmod指令可删除不需要的模块。 参数: ● –a:删除所有目前不需要的模块。 ● –s:把信息输出至syslog常驻服务,而非终端机界面。 (3)Ctrl+C命令 说明:执行该命令终止运行程序。
Linux系统下的vi编辑器 嵌入式系统开发的实验基础 2.vi的基本操作 (1)进入vi。在系统提示符后输入vi及文件名称后,就进入vi全屏幕编辑界面: $ vi myfile 此时是处于命令行模式,按“i”切换到插入模式。 (2)在插入模式下编辑文件,编辑完成后按Esc键回到编辑模式。 (3)退出vi及保存文件。 在命令模式下,按一下“:”冒号键进入命令模式,此时可以保存文件退出vi。例如: :w filename ;将文件以指定的文件名filename保存 :wq ;存盘并退出vi :q! ;不存盘强制退出vi
Linux系统下的vi编辑器 嵌入式系统开发的实验基础 3.vi的常用命令 (1)光标移动命令 h:光标左移一个字符; l:光标左移一个字符; k:光标上移一行; j:光标下移一行; ctrl+b:向文件首翻一页; ctrl+f:向文件尾翻一页; ctrl+u:向文件首翻半页; ctrl+d:向文件尾翻半页;
Linux系统下的vi编辑器 嵌入式系统开发的实验基础 0:移到文章的开头; G:移动到文章的最后; $:光标移动到所在行的行尾; ^:光标移动到所在行的行首。 (2)删除、复制、替换命令 x:删除光标所在处的字符; dd:删除光标所在行; yy:复制光标所在行到缓冲区; p:将缓冲区内的字符贴到光标所在位置; r:替换光标所在处的字符; R:替换光标所到之处的字符,直到按下Esc键为止; u:取消上一次操作。
基于Linux的应用程序的开发步骤 嵌入式系统开发的实验基础 开发Linux应用程序一般分为以下几个步骤。 ● 编写源程序; ● 编写Makefile文件; ● 编译程序; ● 运行和调试程序; ● 将生成的可执行文件加入文件系统。 其中前3个步骤在宿主机上完成,后面的步骤在目标机上完成。 下面以编写Hello程序为例,说明应用程序的开发过程。 1.建立工作目录 [root@arm2410s]# mkdir hello [root@arm2410s]# cd hello