1.61k likes | 1.81k Views
第八章 LINUX 编程基础. ◆ 熟悉嵌入式 Linux 系统开发流程 ◆ 掌握构建交叉工具链的方法 ◆ 熟悉 VMWare 与 RedHat9.0 的安装与使用以及配置宿主机的方法 ◆ 熟悉 Shell 与 Makefile 基本用法。. 8 .1 交叉开发环境的建立. 1. 嵌入式 Linux 系统开发流程 嵌入式 Linux 系统的软件结构. 嵌入式 Linux 系统开发流程. 2. 交叉编译概述
E N D
◆ 熟悉嵌入式Linux 系统开发流程 ◆ 掌握构建交叉工具链的方法 ◆ 熟悉VMWare与RedHat9.0的安装与使用以及配置宿主机的方法 ◆ 熟悉Shell与Makefile基本用法。
8.1 交叉开发环境的建立 1. 嵌入式Linux 系统开发流程 嵌入式Linux 系统的软件结构
2.交叉编译概述 由于一般嵌入式开发系统存储大小有限,通常都要在PC上建立一个用于目标机的交叉编译环境,完成嵌入式系统的开发。交叉编译环境如下图所示。
有时出于减小libc 库大小的考虑,也可以用别的c库来代替glibc。 例如uClibc 、dietlibc 和newlib。 建立一个交叉编译工具链是一个相当复杂的过程,如果不想自己经历复杂的编译过程,网上有一些编译好的可用的交叉编译工具链可以下载。
GNU的工具链源码包可以到: http://www.gnu.org上下载,这个网站有很多GNU软件,其中Linux使用的工具链软件是: Binutils GCC GLIBC GDB
通过这些软件包,可以生成gcc、g++、ar、as、ld等编译链接工具,还可以生成glibc库和gdb调试器。通过这些软件包,可以生成gcc、g++、ar、as、ld等编译链接工具,还可以生成glibc库和gdb调试器。 对于交叉开发工具链来说,从文件名字上加上一个前缀,用来区别本地的工具链,如:arm-linux-gcc,除了体系结构相关的编译选项外,它的使用方法与Linux主机上的gcc相同。所以Linux编程技术对于嵌入式Linux同样适用。
1)Binutils Binutils是一组针对目标系统的二进制开发工具,包括连接器、汇编器和其他用于目标文件和档案的工具。binutils工具包内容如表:
2)GCC GCC(GNU Compiler Collection)是编译器,gcc不但能够支持C/C++语言的编译,而且能够支持FORTRAN JAVA ADA等编程语言。对于C/C++语言的完整支持,需要支持glibc库。下表是GCC软件包内容。
使用GCC编译程序时,编译过程可以被细分为四个阶段:使用GCC编译程序时,编译过程可以被细分为四个阶段: (1)预处理(Pre-Processing) (2)编译(Compiling) (3)汇编(Assembling) (4)链接(Linking)
gcc最基本的用法是∶ gcc [options] [filenames] options:编译器所需要的编译选项 filenames:要编译的文件名。
编译选项: gcc编译器的编译选项大约有100多个,其中多数我们根本就用不到,这里只介绍其中最基本、最常用的参数。 -o output_filename:确定可执行文件的名称为output_filename。如果不给出这个选项,gcc就给出预设的可执行文件a.out。 -c:只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件。
-g:产生调试工具(GNU的gdb)所必要的符号信息,要想对编译出的程序进行调试,就必须加入这个选项。 -O,对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。 -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
3)GLIBC Glibc库是提供系统调用和基本函数的C库,可以编译生成静态库和动态库。完整的GCC需要支持glibc库。一般存放在/lib和/usr/lib目录中。Glibc库的工具如表。
4)GDB 作为GNU的成员之一,GDB(GNU Debug)也是免费的。GDB可以调试C和C++语言程序,功能非常强大。GDB主要完成下面三个方面的功能: (1)启动被调试程序。 (2)让被调试的程序在指定的位置停住。 (3)当程序被停住时,可以检查程序状态(如变量值)。 启动GDB方法: gdb 调试程序名 例:gdb helloworld
例如: #include<stdio.h> void main() { int i; long result=0; for(i=1;i<=100;i++) { result+=i; } printf("result=%d\n",result); }
(1)编译生成可执行 gcc-g tst.c (2)启动GDB gdb tst (3)在main函数处 break main (4)运行程序 run (5)单步运行 next (6)继续运行 Continue
5) Crosstool Crosstool软件实际上是一个脚本,用于编译和测试大多数体系结构的各gcc和glibc的版本组合。从crosstool网站上可以下载到这些编译脚本。它包含了体系结构和gcc和glibc各种组合配置的最小补丁。
Binutils、gcc和glibc的版本需要匹配,越新的版本功能越强大,但是最新版本有可能有存在BUG。这需要不断地测试修正。 对于gcc来说,2.95.x曾经统治了Linux2.4内核时代,它表现得极为稳定。 随着内核的升级,Linux2.6内核需要更高的工具链版本来支持。所以Linux2.6内核最好用gcc3.3以上的版本。
8.1.3 构建交叉工具链 构建交叉编译器首先就是确定目标平台。 在GNU系统中,每个目标平台都有一个明确的格式,这些信息用于在构建过程中识别要使用的不同工具的正确版本。
当在一个特定目标机下运行GCC时,GCC便在目录路径中查找包含该目标规范的应用程序路径。GNU的目标规范格式为CPU-PLATFORM-OS。 例如x86/i386 目标机名为i686-pc-linux-gnu。 本章的目的是讲述建立基于ARM平台的交叉工具链,所以目标平台名为arm-linux-gnu。
通常构建交叉工具链有3种方法 方法一: 分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。 该方法相对比较困难,适合想深入学习构建交叉工具链的读者。如果只是想使用交叉工具链,建议使用方法二或方法三构建交叉工具链。
方法二: 通过Crosstool脚本工具来实现一次编译生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。
方法三: 直接通过网上(ftp.arm.kernel.org.uk)下载已经制作好的交叉编译工具链。 该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的没有灵活性,所以构建所用的库以及编译器的版本也许并不适合自己要编译的程序,同时也许会在使用时出现许多莫名的错误,建议读者慎用此方法。
1. 分步构建交叉编译链 就是一步一步地建立交叉编译链。下面尽可能详细地介绍构建的每一个步骤,读者完全可以根据本节的内容自己独立实践,构建自己的交叉工具链。通过实践可以使读者更加清楚交叉编译器的构建过程以及各个工具包的作用。该方法所需资源如表8.1.7所示。
1)建立工作目录 工作目录就是在什么目录下构建交叉工具链,目录的构建一般没有特别的要求,可以根据个人喜好建立。 # cd /my2410 # mkdir armlinux
在工作目录armlinux下建立3个目录 build-tools、kernel 和 tools。具体操作如下: # cd armlinux # mkdir build-tools kernel tools 其中各目录的作用如下。 (1)build-tools:用来存放下载的binutils、gcc、glibc等源代码和用来编译这些源代码的目录; (2)kernel:用来存放内核源代码; (3)tools:用来存放编译好的交叉编译工具和库文件。
2)建立环境变量 该步骤的目的:方便重复输入路径 声明以下环境变量的目的是在之后编译工具库的时候会用到,很方便输入,尤其是可以降低输错路径的风险。
# export PRJROOT=/home/mike/armlinux # export TARGET=arm-linux # export PREFIX=$PRJROOT/tools # export TARGET_PREFIX=$PREFIX/$TARGET # export PATH=$PREFIX/bin:$PATH 注意,用export声明的变量是临时的变量 ,如果还需要使用这些环境变量就必须重复export操作。 环境变量也可以定义在bashrc文件中,这样当注销或更换控制台时,这些变量就一直有效,就不用总是export这些变量了。
3)编译、安装Binutils Binutils是GNU工具之一,它包括连接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。 安装Binutils工具包含的程序有addr2line、ar、as、c++filt、gprof、ld、nm、objcopy、objdump、ranlib、readelf、size、strings、strip、libiberty、libbfd和libopcodes。
Binutils工具安装依赖于: Bash、Coreutils、Diffutils、GCC、Gettext、Glibc、Grep、Make、Perl、Sed、Texinfo等工具。
下面将分步介绍安装binutils-2.15的过程。 首先解压binutils-2.15.tar.bz2包,命令如下: # cd $PRJROOT/build-tools # tar –xjvf binutils-2.15.tar.bz2
接着配置Binutils工具,建议建立一个新的目录用来存放配置和编译文件,这样可以使源文件和编译文件独立开,具体操作如下: 接着配置Binutils工具,建议建立一个新的目录用来存放配置和编译文件,这样可以使源文件和编译文件独立开,具体操作如下: # cd $PRJROOT/build-tools # mkdir build-binutils # cd build-binutils # ../ binutils-2.15/configure --target=$TARGET --prefix=$PREFIX
其中: –target的含义是制定生成的是 arm-linux 的工具 --prefix 是指出可执行文件安装的位置。执行上述操作会出现很多check信息,最后产生 Makefile 文件。 接下来执行make和安装操作,命令如下: # make # make install
该编译过程较慢,需要数十分钟,安装完成后查看/my2410/armlinux/tools/bin目录下的文件,如果查看结果如下,表明此时Binutils工具已经安装结束。 # ls $PREFIX/bin arm-linux-addr2line arm-linux-ld arm-linux-ranlib arm-linux-strip arm-linux-ar arm-linux-nm arm-linux-readelf arm-linux-as arm-linux-objcopy arm-linux-size arm-linux-c++filt arm-linux-objdump arm-linux-strings
4)获得内核头文件 编译器需要通过系统内核的头文件来获得目标平台所支持的系统函数调用所需要的信息。对于Linux内核,最好的方法是下载一个合适的内核,然后复制获得头文件。需要对内核做一个基本的配置来生成正确的头文件;不过,不需要编译内核。
对于本例中的目标arm-linux,需要以下步骤。 (1)在kernel目录下解压linux-2.6.30.4.tar.gz内核包,执行命令如下: # cd $PRJROOT/kernel # tar –xvzf inux-2.6.30.4.tar.gz (2)接下来配置编译内核使其生成正确的头文件,执行命令如下: # cd linux-2.6.30.4 # make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
其中: ARCH=arm表示是以arm为体系结构 CROSS_COMPILE=arm-linux-表示是以arm-linux-为前缀的交叉编译器 可以用config和xconfig来代替menuconfig,推荐用make menuconfig。 注意在配置时一定要选择处理器的类型,这里选择三星的S3C2410(System Type->ARM System Type->SMDK2410/ARM920T),如下图所示。
配置完退出并保存。 检查一下内核目录中的include/linux/version.h和include/linux/autoconf.h文件是不是生成了,这是编译glibc时要用到的,如果version.h 和 autoconf.h 文件存在,说明生成了正确的头文件。
复制头文件到交叉编译工具链的目录,首先需要在/home/mike/armlinux/tools/arm- linux目录下建立工具的头文件目录inlcude,然后复制内核头文件到此目录下。具体操作如下: # mkdir –p $TARGET_PREFIX/include # cp –r $PRJROOT/kernel/linux-2.6.30.4/include/linux $TARGET_PREFIX/include # cp –r $PRJROOT/kernel/linux-2.6.30.4/include/asm-arm $TARGET_PREFIX/include/asm
5) 编译安装boot-trap gcc 主要是建立arm-linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要C库支持的程序。 后面创建C库也要用到这个编译器,所以创建它主要是为创建C库做准备,如果只想编译内核和BootLoader,那么安装完这个就可以到此结束。