Linux系统移植(一) -- 交叉编译工具链

Linux系统移植(一) – 交叉编译工具链

系统移植在嵌入式开发工作中占据着很重要的作用,我们只有将操作系统移植到特定的开发板上面后,我们才能进行进一步的开发工作。我们编写的应用程序或者驱动程序才能才开发板上面跑起来。系统移植的工作相对来说还是比较繁琐的,有的公司里面也有专门的做系统移植的部门。系统移植虽然繁琐,但是主要也是围绕如下的四个方面来进行的:
1. 搭建交叉开发环境
2. BootLoader的选择和移植
3. kernel的配置、编译、和移植
4. 根文件系统的制作

这里将以Linux系统移植为例,关于其他系统移植的也是离不开上面提到的四个主要部分的。

一、搭建交叉开发环境

很多新手同学或者说是从事上层应用开发的同学可能对这个并不熟悉,因为他们做开发的环境基本是已经搭建好的IDE环境,特别是在windows下面做开发的同学。

首先思考一个问题,我们在Windows下面开发的可执行程序是否能直接在Linux环境下运行?答案是不能!为什么呢?总的来说有两点:
1. 处理器的体系架构不一样,所使用的指令集不同
2. 调用的库可能不同

我们知道大部分Windows PC机一般都是采用因特尔的处理器,而因特尔的处理器一般是X86的架构,使用X86指令集,一般采用CISC(复杂指令集),而大部分嵌入式设备采用ARM 结构的处理器,采用ARM指令集,一般是RISC(精简指令集)。所以在X86上面编译的程序,不能在ARM架构设备上运行。常用的架构还有:MIPS、POWERPC等。不同架构上面程序之间的移植都需要交叉编译。第二个原因,不同操作系统之间所调用的库函数可能不同,所以在Windows上可以跑起来的程序在Linux上不一定能跑起来。当然,平台间不兼容的主要原因是第一个。

在嵌入式开发时,我们常常会在PC上面编译程序然后把编译好的程序放到开发板上面去运行。主要由两点原因:1. PC上面开发更简洁(有大量的可视化的软件能辅助我们开发) 2. CPU更加强大。一般嵌入式开发板CPU频率一般是几百兆赫兹,而PC上CPU一般是几GHZ,编译程序时会更快也会,特别是编译大型程序的时候,这个优势就会更加明显。

交叉编译开发环境一般使用到的硬件有:
1. 开发板
2. PC机
3. 连接PC和开发板的工具。如:串口线、网线、USB线等。

串口线:一般用来帮助我们打印log以及输送我们在PC上敲击的命令到开发板去执行,这个一般需要下载串口调试工具,设置好相关的串口通信(如使用的COM口、波特率等)就好。

USB线:一般用于给开发板供电或者下载程序。在Android和支持adb shell的Linux上,我们还能用它去在开发板上执行命令、调试、看log。

网线:一般用来下载程序,就是将我们在PC上面编译好的程序下载到开发板上面去运行。当然了,应该支持相关的网络协议才可以实现。

二、使用到的网络服务

  1. TFTP服务
    主要用于实现文件的下载,比如开发调试的过程中,主要用tftp把要测试的bootloader、kernel和文件系统直接下载到内存中运行,而不需要预先烧录到Flash芯片中,一方面,在测试的过程中,往往需要频繁的下载,如果每次把这些要测试的文件都烧录到Flash中然后再运行也可以,但是缺点是:过程比较麻烦,而且Flash的擦写次数是由限的;

    另外一方面:测试的目的就是把这些目标文件加载到内存中直接运行就可以了,而tftp就刚好能够实现这样的功能,因此,更没有必要把这些文件都烧录到Flash中去这个需要我们在开发板和PC机上面同时跑tftp服务,一个做server、一个做client,同时设置二者的ip在同一网段。

  2. NFS服务
    主要用于实现网络文件的挂载,实际上是实现网络文件的共享,在开发的过程中,通常在系统移植的最后一步会制作文件系统,那么这是可以把制作好的文件系统放置在我们开发主机PC的相应位置,开发板通过nfs服务进行挂载,从而测试我们制作的文件系统是否正确,在整个过程中并不需要把文件系统烧录到Flash中去,而且挂载是自动进行挂载的,bootloader启动后,kernel运行起来后会根据我们设置的启动参数进行自动挂载,因此,对于开发测试来讲,这种方式非常的方便,能够提高开发效率。

    另外,还有一个名字叫samba的服务也比较重要,主要用于文件的共享,这里说的共享和nfs的文件共享不是同一个概念,nfs的共享是实现网络文件的共享,而samba实现的是开发主机上Windows主机和Linux虚拟机之间的文件共享,是一种跨平台的文件共享,方便的实现文件的传输。Samba可能小伙伴不太熟悉,其实我们平常做开发时用到的是很多的,一般稍大点儿的公司都会使用代码服务器,代码一般放到服务器上面,我们平常需要开发就只能通过本地电脑去连接服务器,然后在上面做开发,这个就用到了Samba的服务功能。

    以上这几种开发的工具在嵌入式开发中是必备的工具,对于嵌入式开发的效率提高做出了伟大的贡献,因此,要对这几个工具熟练使用,这样你的开发效率会提高很多。等测试完成以后,就会把相应的目标文件烧录到Flash中去,也就是等发布产品的时候才做的事情,因此对于开发人员来说,所有的工作永远是测试。

    通过前面的工作,我们已经准备好了交叉开发环境的硬件部分和一部分软件,最后还缺少交叉编译器。交叉编译器主要用来在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,简单点儿来讲就是在PC上编译能够在开发板上面运行的程序。相对于交叉编译,平常做的编译叫本地编译,也就是在当前平台编译,编译得到的程序也是在本地执行。用来编译这种跨平台程序的编译器就叫交叉编译器,相对来说,用来做本地编译的工具就叫本地编译器。所以要生成在目标机上运行的程序,必须要用交叉编译工具链来完成。

这里又有一个问题,不就是一个交叉编译工具吗?为什么又叫交叉工具链呢?原因很简单,程序不能光编译一下就可以运行,还得进行汇编和链接等过程,同时还需要进行调试,对于一个很大工程,还需要进行工程管理等等,所以,这里 说的交叉编译工具是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils(主要包括汇编程序as和链接程序ld)、gcc(为GNU系统提供C编译器)和glibc(一些基本的C函数和其他函数的定义) 3个部分组成。有时为了减小libc库的大小,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。

那么,如何得到一个交叉工具链呢?是从网上下载一个“程序”然后安装就可以使用了吗?回答这个问题之前先思考这样一个问题,我们的交叉工具链顾名思义就是在PC机上编译出能够在我们目标开发平台比如ARM上运行的程序,这里就又有一个问题了,我们的ARM处理器型号非常多,难道有专门针对我们某一款的交叉工具链吗?如果有的话,可以想一想,这么多处理器平台,每个平台专门定制一个交叉工具链放在网络上,然后供大家去下载,想想可能需要找很久才能找到适合你的编译器,显然这种做法不太合理,且浪费资源!因此,要得到一个交叉工具链,就像我们移植一个Linux内核一样,我们只关心我们需要的东西,编译我们需要的东西在我们的平台上运行,不需要的东西我们不选择不编译,所以,交叉工具链的制作方法和系统移植有着很多相似的地方,也就是说,交叉开发工具是一个支持很多平台的工具集的集合(类似于Linux源码),然后我们只需从这些工具集中找出跟我们平台相关的工具就行了,那么如何才能找到跟我们的平台相关的工具,这就是涉及到一个如何制作交叉工具链的问题了。

通常构建交叉工具链有如下三种方法:
方法一 :分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。该方法相对比较困难,适合想深入学习构建交叉工具链的 。如果只是想使用交叉工具链,建议使用下列的方法二构建交叉工具链。

方法二: 通过Crosstool-ng脚本工具来实现一次编译,生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。

crosstool-ng是一个脚本工具,可以制作出适合不同平台的交叉编译工具链,在进行制作之前要安装一下软件:
$ sudo apt-get install g++ libncurses5-dev bison flex texinfo automake libtool patch gcj cvs cvsd gawk

crosstool脚本工具可以在http://ymorin.is-a-geek.org/projects/crosstool下载到本地,然后解压,接下来就是进行安装配置了,这个配置优点类似内核的配置。
主要的过程有以下几点:

  1. 设定源码包路径和交叉编译器的安装路径
  2. 修改交叉编译器针对的构架
  3. 增加编译时的并行进程数,以增加运行效率,加快编译,因为这个编译会比较慢。
  4. 关闭JAVA编译器 ,减少编译时间
  5. 编译
  6. 添加环境变量
  7. 刷新环境变量。
  8. 测试交叉工具链

方法三 :直接通过网上下载已经制作好的交叉编译工具链。该方法的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的,没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名其妙的错误,建议各位同学慎用此方法。

在交叉编译环境搭建好以及交叉编译工具准备好后,我们就需要进行下一步了:BootLoader的移植

你可能感兴趣的:(系统移植)