《ARM嵌入式Linux系统开发详解.ppt》由会员分享,可在线阅读,更多相关《ARM嵌入式Linux系统开发详解.ppt(541页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第1章 嵌入式系统入门,时下计算机领域最热门的一个词可能就是嵌入式系统了。翻开计算机的杂志和书籍,许多地方都能见到嵌入式系统的字眼。其实,不仅在书籍杂志上,嵌入式系统和每个普通人的生活联系都是很紧密的。本章从应用角度出发介绍什么是嵌入式系统,带读者进入嵌入式系统开发的领域,主要内容包括: 嵌入式系统定义 嵌入式系统的应用领域 嵌入式系统的发展趋势,1.1 什么是嵌入式系统,对于没有接触过的人来说,嵌入式系统这个词可能显得比较深奥,甚至充满一些神秘色彩。其实嵌入式系统和普通人的生活非常紧密,如日常生活中使用的手机、微波炉、有线电视机顶盒等,都属于嵌入式系统。与通常使用的PC机相比,嵌入式系统的形
2、式变化多样、体积小,可以灵活地适应各种设备的需求。因此,可以把嵌入式系统理解为一种为特定设备服务的,软件硬件可裁剪的计算机系统。嵌入式系统的英文名称是Embedded System。 从嵌入式系统的定义可以看出,一个嵌入式系统具备了体积小、功能专一、软硬件可裁剪的特点。这些特点也能反映出嵌入式系统与传统的PC机有着不同之处。本书使用常见的ARM嵌入式系统为例讲解嵌入式Linux系统移植和开发技术。,1.2 嵌入式系统应用领域,从嵌入式系统的特点可以看出它的应用领域是很广泛的。不仅在家电上,在其他的领域也有很大的需求。本节介绍一些嵌入式应用的领域。,1.2.1 家用电器,家用电器里最常见的可能就
3、算是手机了。手机是一个典型的嵌入式系统。,1.2.2 交通工具,大家最常使用的交通工具就是汽车了,不管是公交车、私家车还是其他的各种专用车辆,都有嵌入式系统的身影。,1.2.3 公共电子设施,银行的ATM自动取款机是一种常见的公共电子设备。,1.3 嵌入式系统发展,从1946年第一台现代电子计算机诞生以来,计算机始终朝着两个方向发展:一个方向是体积大型化、处理能力超强的大型计算机;另一个方向是超体积小型话、功能多样化发展。这两个发展方向没有高低之分,都是由于实际需求带动发展。计算机大型化发展出现了很多的超级计算机,各国都在研制自己的大型计算机。在计算机小型化的发展道路上,可谓是种类繁多。不仅有
4、个人电脑(PC),还有各种个人数字助理(PDA)。嵌入式系统是计算机系统小型化发展的一个热门的分支。,1.3.1 嵌入式微控制器,嵌入式微控制器也就是传统意义上的单片机,它可以说是目前嵌入式系统的前身。单片机就是把一个计算机的主要功能集成到了一个芯片上,简单说就是一个芯片就是一个计算机。它的特点是体积小、结构简单、便于开发以及价格经济。,1.3.2 嵌入式微处理器,单片机的发展时间较早,处理能力很低,只能用在一些相对简单的控制领域。嵌入式微处理器是近几年随着大规模集成电路发展同步发展起来的。与单片机相比,嵌入式微处理器的处理能力更强。目前主流的嵌入式微处理器都是32位的,而单片机多是8位和16
5、位的。 嵌入式处理器在一个芯片上集成了复杂的功能,同时一些微处理器还把常见的外部设备控制器也集成到芯片内部。以ARM芯片为例,ARM体系在内部规定了一个32位的总线,厂商可以在总线扩展外部设备控制器。三星的ARM9芯片S3C2440A把常见的串行控制器、RTC控制器、看门狗、I2C总线控制器甚至LCD控制器等都集成在了一个芯片内,可以提供强大的处理能力。,1.3.2 嵌入式微处理器,1.3.3 未来嵌入式系统发展的方向,随着微电子技术的不断发展以及电子制造工艺的进步(目前已经可以制造出65纳米的芯片),嵌入式系统硬件的体积会不断缩小,系统稳定性也在不断增强,可以把更多的功能集成在一个芯片上。另
6、外在功耗方面也不断降低,这样使嵌入式设备在自带电源的情况(如使用电池)会使用更长的时间,而且设备的功能也更强大。 此外随着网络的普及和IPv6技术的应用,越来越多的嵌入式设备也会加入到网络中。将来家中的微波炉或者洗衣机都可以通过无线接入网络,被其他设备控制。,1.4 典型的嵌入式系统组成,嵌入式系统与传统的PC机一样,也是一种计算机系统,是由硬件和软件组成的。硬件包括了嵌入式微控制器和微处理器,以及一些外围元器件和外部设备;软件包括嵌入式操作系统和应用软件。 与传统的计算机不同的是,嵌入式系统种类繁多。许多的芯片厂商、软件厂商加入其中,导致有许多的硬件和软件,甚至解决方案。一般来说,不同的嵌入
7、式系统软硬件是很难兼容的,软件必须修改而硬件必须重新设计才能使用。虽然软硬件种类多,但是不同的嵌入式系统还有很多相同之处的。,1.4 典型的嵌入式系统组成,1.5 小结,本章是全书的第一章,为读者介绍了嵌入式系统的基本常识、组成结构,通过实例给读者对嵌入式系统一个初步的认识。本章的知识相对比较笼统,偏重一些概念方面的介绍,读者可以结合实际生活理解,加深对嵌入式系统的认识。第2章讲解嵌入式软件和硬件系统基本知识。,第2章 嵌入式软硬件系统,在学习嵌入式开发之前,需要了解一下嵌入式系统基本知识。嵌入式系统是由软件和硬件组成的,与传统的PC不同,在设计嵌入式系统的时候通常是软件和硬件都需要设计。对于
8、一个嵌入式系统开发来说,无论是硬件开发人员还是软件开发人员,都需要掌握基本的软件和硬件知识。本章的主要目的是通过讲解基本的软硬件知识,帮助读者建立嵌入式系统概念,主要内容包括: 模拟电路和数字电路 基本的数制转换 计算机的工作原理 软件的基础知识 操作系统概要,2.1 电路基本知识,初中物理知识讲过,电流就是电流通过的路径。一个最简单的电路是由电源、负载和导线构成的。复杂的电路还有电阻、电容、晶体管、集成电路等元件。这些元件的功能不同,通过不同的组织方式构成了不同功能的电路。无论什么样的电路,最终的功能都是处理电子信号的。按照电子信号的工作方式可以把电路分成模拟电路和数字缏贰,2.1.1 什么
9、是模拟电路,处理模拟信号的电路称作模拟电路。模拟信号的特点是信号是线性变化的,意思是信号变化是连续的。如经常使用的收音机、电视机和电话都是使用的模拟信号。常见的模拟电路有变压电路、放大电路。评估一个模拟电路常见的参数有放大率、信噪比和工作频率等。模拟电路是数字电路的基础,数字电路可以看做是模拟电路的一种特殊形式。,2.1.2 什么是数字电路,数字电路顾名思义是处理数字信号的电路,通常数字电路具有逻辑运算和逻辑处理的功能。与模拟信号不同,数字信号使用电压的高低或者电流的有无表示逻辑上的1或0,因此数字电路可以方便地表示出二进制数。数字电路可以分成脉冲电路和逻辑电路两部分,脉冲电路负责对信号变换和
10、测量;逻辑电路负责处理数字逻辑。 与模拟电路不同,数字电路关心的是信号状态的变化。通过数字逻辑可以处理复杂的二进制信息,因此数字电路是计算机的基础。由于数字电路的工作特点,它具有电路结构简单、容易加工制造等优点,可以大批量的生产制造,成本也变得低廉。数字电路广泛应用在测量、科学计算、自动控制等领域。,2.1.3 数制转换,计算机是由数字电路构成的,其内部数据的传输和处理都使用二进制方式。日常生活中普遍使用十进制方式表示数字,所以在使用计算机的时候需要用到数制转换。常见的有二进制到十进制的转换,从事嵌入式开发经常会用到十六进制,有的时候还会用到八进制。 二进制的特点是“逢2进1”。如十进制的0对
11、应二进制的0,十进制的1对应二进制的1,十进制的2对应二进制的10,以此类推。从这个推演规律中可以看出,二进制数从右往左每个位数都是2的位数次幂。举个例子,二进制数1010转换为十进制数: (1010)2 = (23x1) + (22x0) + (21x1) + (20 x0) = 8 + 0 + 2 + 0 = (10)10,2.1.3 数制转换,2.2 计算机组成原理,现代计算机的构造越来越复杂,功能也日新月异。但是计算机的组成结构从本质来说仍然是相同的。一个计算机系统硬件是由中央处理器、存储系统、总线系统和输入输出系统几个基本部分组成的。本节从计算机系统结构发展的角度介绍计算机组成和工作
12、原理。,2.2.1 计算机体系的发展,计算机是由硬件系统和软件系统两大部分组成的。按照功能又可以划分为指令系统、存储系统、输入输出系统等。计算机体系结构简单的说就是研究计算机各系统和组成部分结构的一门学问。计算机的诞生到现在时间仅有半个世纪,但是计算机体系结构却有很大的发展,出现了许多的体系结构设计思想和设计方法。从存储结构来说可以把计算机体系分成冯诺依曼结构和哈佛结构。,2.2.2 中央处理器,中央处理器英文全称是(Central Process Unit),简称CPU,是一个计算机系统的核心。CPU是由运算器、控制器、寄存器和内部总线组成的。在CPU之外再加入总线,存储设备输入输出设备就可
13、以构成一个完整的计算机系统。 CPU有几个重要的参数,包括工作频率、字长、指令集和缓存。工作频率通常是用户最多听到的参数,一个CPU的工作频率包括了主频和外频以及外部总线频率。主频是CPU的实际工作频率,外频是CPU工作的基准频率,还有一个是总线的工作频率。一般来说,工作频率越高的CPU执行指令的速度就越快,但是也不完全如此。,2.2.3 存储系统,计算机在工作中需要从内部存储器中读取指令和数据,并且把计算的结果存入外部存储器。由于材料和价格因素的限制,计算机的存储器件在容量、速度等方面需要匹配。存储系统的作用就是设计一个让各种存储器相互配置达到最优性价比的方案。,2.2.4 总线系统,总线是
14、CPU连接外部设备的通道。通常包括数据总线(DataBus)、地址总线(AddressBus)和控制总线(ControlBus)。地址总线负责向外部设备发送地址信息;数据总线负责从外部设备读取或者写入信息;控制总线负责发送信号控制外部设备。 计算机的总线系统是由总线和相应的控制器构成的。如嵌入式系统中常见的I2C总线和SPI总线,特点是控制简单,成本低廉,本书后面会做具体介绍。其他的还有PCI总线,支持复杂的功能和很高的系统吞吐量。 总线的出现规范了CPU和外设之间的通信标准,简化了外部器件的设计。使用一些通用的总线可以有效降低开发成本。,2.2.5 输入输出系统,输入输出系统由外部设备和输入
15、输出控制器组成,是CPU与外部通信的系统。CPU通过总线与输入输出系统相连。由于外部设备的速度差异,CPU可以使用不同的方式控制外部设备的访问。常见的有轮询方式、中断控制方式和DMA方式。 程序中断方式最简单,CPU通过不断的查询某个外部设备的状态,如果外部设备准备好,就可以向其发送数据或者读取数据。这种方式由于CPU不断查询总线,导致指令执行受到影响,效率非常低。,2.3 软件基础知识,嵌入式系统的基础是硬件,软件是嵌入式系统的灵魂。离开了软件,一个系统的功能就无法发挥。因此软件设计开发是嵌入式系统开发的一个重要环节。本节介绍软件的基础知识,开发流程以及基本的技术。,2.3.1 什么是软件,
16、使用过计算机的读者都使用过各种各样的软件,例如最常见的Word文字处理软件,还有上网使用的浏览器等。严格的说,软件是由程序和文档构成的,程序是一组按照特定结构组织的指令和数据集合。 通常软件可以分成系统软件和应用软件,以及目前兴起的介于二者之间的中间件软件。系统软件是使用计算机提供的基本功能,例如操作系统和数据库系统。它们都不是针对某种特殊需求,而是面向通用的领域。应用软件是针对某种特殊需求设计的,一般来说具有专门的功能。比如MP3播放软件就是针对播放音乐设计的。 软件的另一个组成部分是文档。随着软件复杂程度的提高,文档也越来越重要。常见的软件文档有开发文档和用户文档,前者面向开发人员,后者面
17、向最终用户。软件开发人员应该树立起编写文档的好习惯。,2.3.2 软件开发流程,软件开发流程是软件在开发过程中需要走的步骤,经过几十年的发展形成一套公认的开发流程。大致可以分成4个部分:需求分析、设计、编码调试、测试和维护。,2.3.3 常见的软件开发模型,软件的发展过程中,经过前人的总结,设计出几种软件开发模型。软件开发模型指定了软件开发流程中的规范和参考原则,指导开发人员按照特定的步骤工作。但是,由于现实的差异性,很少有适用与所有软件的开发模型,有一些经过验证比较有效的模型供开发人员参考。常见的有瀑布开汀隽靠鸵约跋衷诒冉先让诺耐骋蝗砑停UML)。,2.3.4 计算机编程语言,计算机内部是通
18、过执行指令完成各种操作的,无论是指令还是数据在计算机内部都使用二进制表示,对于用户的识别和输入都很困难。计算机编程语言就是为解决这个问题设计的。计算机编程语言是一种有规范格式和语法供人类描述计算机指令的字符串集合。举个例子来说,计算机内部使用二进制10100101表示一个求加法操作,计算机语言可以通过add字符串表示这个加法操作,便于人类识别。 计算机语言可以分成机器语言、汇编语言和高级语言。其中机器语言是供计算机本身识别的,为二进制串。汇编语言是对机器语言的抽象,其实质与机器语言是相同的。汇编语言的指令与机器语言是一一对应的。此外,汇编语言还设计了伪指令和宏指令,帮助编程人员提高开发效率。汇
19、编语言是依赖体系结构的,在一种CPU上能执行的汇编语言在其他的CPU很可能就无法执行了。,2.3.5 数据结构,数据的物理结构描述数据元素的存储结构,依赖于具体的计算机实现。例如,一个统计表格是数据元素之间的逻辑结构,但是把表格存放到计算机中需要考虑存储结构,可以按照行的顺序存储,也可以按照列的顺序存储,这就是数据的物理结构。 数据结构还定义了数据元素上的操作方法,通常也称作算法。算法可以理解为一种思路。例如,对10个无序的数字按照大小排序,可以有冒泡排序、二分排序、插入排序等多种方法。在计算机编程中,一个好的算法可以起到事半功倍的效果。,2.4 操作系统知识,现代计算机的应用软件都是在操作系
20、统下面工作的。嵌入式系统早期应用程序是直接运行在CPU上,比如单片机。随着嵌入式系统硬件处理能力的提升,应用也越来越复杂,目前主流的嵌入式系统都配备了操作系统,应用软件使用操作系统提供的功能。本节介绍操作系统的知识。,2.4.1 什么是操作系统,操作系统是一类特殊的系统软件。它管理整个系统的所有硬件和软件,通常是整个计算机系统中最接近硬件的系统软件。操作系统屏蔽了硬件的底层特性,向应用软件提供了一个统一的接口。对于应用软件来说,不需要知道硬件的具体特性,使用操作系统提供的接口即可完成相应的功能。除此之外,操作系统通过特定的算法统筹安排整个计算机系统软硬件资源,使计算机的资源利用率更高,甚至获得
21、比硬件更多的功能。 操作系统是软件领域一个重要部分。常见的嵌入式操作系统有cLinux、vxWorks等。本书第4章将详细讲解嵌入式Linux操作系统以及与其他系统之间的对比。,2.4.2 操作系统发展历史,最早的计算机没有操作系统。在同一时间,用户只能通过打孔机等外部设备把程序输入,计算机按照程序执行。如果程序出现问题,整个机器就会停止工作。后来把常用的程序设计成库装入计算机,方便用户使用,这可以算是操作系统的雏形。 早期的操作系统多种多样,在大型机领域,几乎每个系列的计算机都有自己的操作系统。这种方式造成资源很大的浪费,同样功能的程序在不同的机器上由于操作系统的不同无法运行。后来,AT s
22、ee the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gdb -version GNU gdb 6.3.50_2004-12-28-cvs (cygwin-special) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, a
23、nd you are welcome to change it and/or distribute copies of it under certain conditions. Type show copying to see the conditions. There is absolutely no warranty for GDB. Type show warranty for details. This GDB was configured as i686-pc-cygwin.,5.3 Linux常用工具,目前大多数的Linux发行版都提供了图形界面作为默认界面,但是,命令行工具在Li
24、nux仍然很重要。Linux工具的特点是一个程序包含的功能尽量专一,不同的程序通过文件、管道等进程间数据共享的方法可以组合使用,达到处理复杂功能的目的。学习使用Linux系统,命令行工具是基础。GNU的命令行工具都有相同的特点,初学者从一些基本的工具入手,比较容易学习。,5.3.1 Linux Shell和常用命令,使用过DOS系统和Windows中断控制台的人对命令行界面都有一定体会。与这些系统不同,Linux的命令行是通过一种叫做Shell的程序提供的。Shell程序负责接受用户的输入,解析用户输入的命令和参数,调用相应的程序,并给出结果和出错提示。Linux支持多种Shell程序,早期的
25、Shell程序功能比较单一,现在主流的Linux发行版使用bash作为默认的Shell。Bash支持功能强大的脚本、命令行历史记录、终端彩色输出等功能。Shell是Linux的外壳,用户通过Shell使用系统提供的功能。 在Linux系统中,仅有内核还是不够的,需要应用程序支持才能发挥内核提供的功能。无论是Linux发行版还是嵌入式Linux开发板上的系统,都提供了常见的一些命令。,5.3.1 Linux Shell和常用命令,5.3.1 Linux Shell和常用命令,5.3.2 文本编辑工具vi,Linux系统的文本编辑工具有许多,其中使用最广泛的就是vi编辑器了。vi编辑器的功能十分强
26、大,并且非常小,适合安装在嵌入式系统使用。vi虽然功能强大,但是对于初学者来说,上手比较困难,初学者往往被vi奇怪的操作弄的失去学习的信息。本书有关vi的使用仅涉及基本操作,目的是帮助初学者学习vi的基本操作。更高级的vi操作读者可以参考vi的帮助文档。 vi编辑器支持编辑模式、浏览模式、插入模式和可视模式四种模式。其中,插入模式包括了插入文本和替换文本两种模式。当启动vi的时候,默认进入浏览模式。浏览模式只能查看和删除文档内容,但是不能修改;编辑模式用户可以修改文档内容,与普通的文本编辑器相同;覆盖模式下用户输入的内容会覆盖光标所在位置的文本;可视模式提供了一种选择文本的方法,可以使用键盘完
27、成鼠标选择文本的功能。,5.3.2 文本编辑工具vi,5.3.3 搜索工具find和grep,find和grep是Linux系统最常用的两个搜索工具。这两个工具不同的是find用于查找文件,grep用于查找文件内容。 grep支持正则表达式(一种描述字符串特征的语法),通过在一个或多个文件中搜索字符串,符合的内容被送到屏幕显示。grep工具不会修改文件内容。grep通过返回值表示搜索状态,如果搜索成功返回0,如果失败返回1,如果搜索的文件不存在返回2。因此,grep可以用于shell脚本。,5.3.4 FTP工具,FTP是标准的互联网文件传输协议,被广泛的应用于网络文件传输,是不同机器间文件传
28、输简单有效的方法。FTP协议允许传输二进制和文本文件。在许多系统上都提供了FTP客户端软件,用来从FTP服务器下载或者上传文件。本节介绍的FTP客户端工具可以在Linux系统和Windows系统上使用,是一种简单易用的文件传输手段。,5.3.4 FTP工具,5.3.5 串口工具minicom,串口是嵌入式开发使用最多的通信方式。Linux系统提供了一个串口工具minicom,可以完成复杂的串口通信工作。本节介绍minicom的使用。首先是安装mimicom,在Ubuntu Linux系统shell下输入“$ sudo apt-get install minicom”回车后即可安装minicom
29、软件。软件安装好后,第一次使用之前需要配置minicom。,5.5 Windows常用工具,嵌入式开发的开发环境和运行环境往往不是同一台机器。作为开发环境,Windows下通常运行一些客户端和代码管理工具、文档管理工具等。本节介绍Windows下常用的两个工具。,5.5.1 代码编辑管理工具SourceInsight,SourceInsight是一个功能强大的代码管理工具。该工具可以轻松管理代码庞大的工程,提供了丰富的编辑功能,支持函数、变量的类型定义查看、跳转等。SourceInsight对C语言代码支持最好,本节介绍SourceInsight安装和使用。 1设置SourceInsight工
30、程 2SourceInsight特色功能,5.5.2 串口工具XShell,在5.3.5节介绍了Linux下的串口工具minicom,本节介绍一个Windows下比较好用的串口工具XShell。实际上,XShell不仅支持串口连接,还可以连接Telnet服务器、SSH服务器等。,5.6 ARM集成开发环境ADS,集成开发环境英文Integrated development environment,缩写是IDE。在没有IDE之前,开发软件过程中的编辑,编译,调试需要不同的工具操作,不仅效率低而且容易出错。IDE的作用是把编辑、编译和调试等工具集成在一起,并且向用户提供一个图形界面的开发环境。AR
31、M开发有标准的开发环境ARM Development Suit,简称ADS。,5.6.1 ADS集成开发环境介绍,ADS是ARM公司推出的ARM集成开发工具,目前最新版本是1.2,只能在Windows系统安装。ADS包括程序库、命令行开发工具、图形界面、调试工具和代码编辑器等。本节介绍一下ADS自带的命令行工具。 1C语言编译器armcc 2C+语言编译器armcpp,5.6.2 配置ADS调试环境,在使用ADS之前,需要安装ADS开发环境。ADS是一个商业软件,需要支付版权费用才可以使用,对于没有购买版权的用户会受到功能限制。,5.6.3 建立自己的工程,本节介绍如何在ADS环境下建立自己的
32、工程并且编译生成目标文件。,5.7 小结,本章讲解了嵌入式Linux开发环境,包括系统环境、开发工具、辅助工具等。开发工具是嵌入式开发过不可缺少的,每种工具都有自己的用途和范围,读者应该多实践,掌握常见的开发工具使用方法。第6章开始介绍基本的程序开发知识。,第6章 第一个Linux应用程序,学习嵌入式程序开发首先从最简单的程序开始。一个最基本的Linux应用程序可以涵盖编程的所有基本知识,通过编写Linux可以快速入门程序开发。本章目的是通过实际的程序向读者介绍Linux程序的基本框架和工作流程。主要内容如下: 编写一个最基本的应用程序 分析程序的执行过程 程序生成过程 程序编译过程管理,6.
33、1 向世界问好 Hello,World!,很多的编程书籍都以输出一行“Hello,World!”向初学者展示如何编写程序。这个程序很简单,却展示了C程序的基本要素:语法格式、引用头文件、调用库函数等。本节展示了程序的编辑、编译和执行相关知识。,6.1.1 用vi编辑源代码文件,在5.3.2小节介绍了vi编辑器的用法,现在使用vi编辑器编写第一个源代码文件。具体操作过程如下: 1创建源代码文件hello_test.c 2编写源代码 3保存退出,6.1.2 用gcc编译程序,编辑好源文件hello_test.c文件后,需要把它编译成可执行文件才可以在Linux下运行。在控制台模式当前目录,输入以下
34、命令完成编译: gcc hello_test.c,6.1.3 执行程序,到目前为止,第一个程序已经编译好了,下面就是执行程序了。在大多数的Linux系统上,都是通过一个名为PATH的环境变量来管理系统可执行程序的路径的,但是不幸的是这个变量里并没有包含了当前路径的./,所以需要按照下面的方式执行程序: ./a.out 执行a.out程序后,输出结果如下: rootslash dev_test# ./a.out Hello,World!,6.2 程序背后做了什么,前面讲了程序如何编辑和编译,并且展示了程序的输出结果。可能有人会问程序是如何输出在屏幕上的。带着这个问题,这一节从程序加载和执行的过程
35、,分析一下Linux应用程序是如何在计算机上运行的。实例6-1所示的基本程序涵盖了执行一个Linux应用程序所有的细节。,6.2.1 程序执行的过程,一个Linux程序的加载和执行过程。,6.2.2 窥视程序执行中的秘密,上面的程序执行过程比较难理解,这里推荐使用strace工具分析这个程序的执行流程。在执行a.out的那个目录,输入以下命令: dev_userlocalhost dev_user$ strace ./a.out,6.2.3 动态库的作用,Linux系统有两种程序库,一种是被称作静态库(static library),在程序连接的时候,把库函数的目标代码和程序连接在一起;还有一
36、种就是前面提到的动态库(shared library),从英文字面翻译,动态库可以翻译为共享库。 动态库是Linux系统最广泛的一种程序使用方式,它的工作原理是相同功能的代码可以被多个程序共同使用。在程序加载的时候,内核会检查程序使用到的动态库是否已经加载到内存,如果没有加载到内存,则从系统库路径搜索并且加载相关的动态库;如果动态库已经被加载到内存,程序可以直接使用而扌爰釉亍 从动态库的工作原理可以看出,任何一个动态库仅会被系统加载一次。使用程序动态库还有一个好处,就是可以减小应用程序占用的空间和加载时间。,6.3 程序如何来的 - 编译的全部过程,在6.1.2节,通过命令行输入gcc hel
37、lo_test.c就可以编译出一个可执行文件a.out。在使用gcc编译c语言源代码文件的时候,gcc隐含进行了两个过程:编译和连接。所以确切的说,应该是编译连接c语言源代码文件,本节就讲一下这个过程。,6.3.1 编译源代码,编译的目的是把人书写的高级语言代码翻译成目标程序的语言处理程序,编译用的程序(例如gcc)也可以称为编译系统。 一个编译系统把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析、语法分析、中间代码生成、代码优化和目标代码生成。其中主要阶段是词法分析和语法分析,也可以称为源代码分析,分析过程中发现有语法错误,给出提示信息。 1词法分析 2语法分析 3中间代码生成 4
38、代码优化 5目标代码生成,6.3.2 链接目标文件到指定的库,源代码经过编译以后,需要链接才可以在Linux系统运行,链接的作用是把代码中调用的系统函数和对应的系统库建立关系,设置程序启动时候的内存,环境变量等,以及程序退出的状态,释放占用的资源等操作,这些背后的工作对用户都是隐含的。gcc在连接用户目标文件的时候会根据用户代码使用不同的函数连接对应的动态或者静态库(根据连接选项,默认是动态库),同时,还会对所有的目标文件连接固定的预编译好的系统目标文件,这几个预编译好的目标文件用来完成程序初始化,结束时的环境设置等。,6.4 更简单的办法用Makefile管理工程,6.1.2节讲述了可以使用
39、如下的方法编译一个链接动态库的程序: gcc hello_test.c 以及使用如下的方法编译一个静态程序: gcc static hello_test.c,6.4.1 什么是Makefile,Makefile是一个文本文件,是GNU make程序在执行的时候默认读取的配置文件。Makefile有强大的功能,它记录了文件之间的依赖关系,通过比对目标文件和依赖文件的时间戳,决定是否需要执行相应的命令;同时,Makefile还可以定义变量,接收用户传递的参数变量,通过这些元素的相互配合,省去了繁杂的编译命令,不仅节省时间,也减小了出错的概率。,6.4.2 它是如何工作的,Makfile的工作原理是
40、通过比对目标文件和依赖文件的时间戳,执行对应的命令。 Makfile的语法结构如下: (目标文件):(依赖文件1)(依赖文件2)(依赖文件) (命令1) (命令2) (命令),6.4.3 如何使用Makefile,仍然以编译hello_test.c文件为例,下面的步骤使用Makefile编译和管理hello_test.c。 (1)创建Makefile文件。在hello_test.c所在的目录输入vi Makefile。 (2)输入Makefile的内容。在vi插入模式,输入下面的内容。 hello_test : hello_test.c gcc o hello_test hello_test.
41、c clean : rm -fr hello_test *.o *.core (3)使用make管理程序。,6.4.4 好的源代码管理习惯,在一个软件项目中,往往会将不同功能的代码放在不同的文件中,这时候,一个好的代码管理方法就显得很重要,凌乱的代码分布不仅对调试带来很多麻烦,对以后的升级和维护都是一个不小的挑战。这里给出几个代码管理的建议: 1把不同功能的代码放在不同的文件,并且把必要的函数放在对应的头文件 2对软件模块划分层次,6.5 小结,本章从一个简单的应用程序入手,介绍了开发一个Linux应用程序的流程。通过实例分析了编译和连接的原理,并且剖析了程序执行的过程。最后讲述了Makefi
42、le管理工程文件如何管理软件代码。请读者多实践,只有不断的实践才能对这部分的知识深入理解。第7章讲解Linux应用程序开发的基础知识。,第7章 Linux应用程序编程基础,Linux系统的应用程序是为了完成某项或者某些特定任务的计算机程序,应用程序和文档组成了软件。应用程序都是在操作系统基础上运行的,Linux应用程序运行在用户模式,可以通过Shell或者图形界面与用户交互。应用程序运行在独立的进程,拥有自己独立的地址空间,通俗的说,在一个应用程序看来,他自己拥有计算机的资源,并不知道其他应用程序的存在。本章讲解Linux应用程序开发的重要概念,主要内容如下: C内存管理 ANSI C文件读写
43、操作 POSIX文件读写操作,7.1 内存管理和使用,内存管理是计算机编程的一个重要部分,也是许多程序员头疼的一个部分。在目前的嵌入式系统中,资源仍然是有限的。在程序设计的时候,内存管理十分重要。C程序的内存管理灵活,接口简单,这也是初学者容易出错的根本,读者在学习本节内容的时候应注重多实践。本节首先讲解Linux程序的基本结构,之后介绍C程序的内存管理函数,最后给出了C程序内存管理的实例。,7.1.1 堆和栈的区别,1栈 栈(stack)是一个由编译器分配释放的区域,用来存放函数的参数,局部变量等。操作方式类似于数据结构教材里的栈。当调用函数时,被调用函数的参数和返回值被存储到当前程序的栈区
44、,之后被调用函数在为自身的自动变量和临时变量在栈区上分配空间。当函数调用返回时,在栈区内的参数返回值,自动变量和临时变量等会被释放。这就是为什么C语言函数参数如果不是指针的话,被修改的参数结果用户无法得到的原因。 函数的调用和栈的使用方式保证了不同函数内部定义相同名字的变量不会混淆。栈的管理方式是FILO(First In Last Out),称作先进后出,学过数据结构的读者知道,栈内的数据是在一个方向管理的,先到达的数据最后被读出来,生活中就有这样的例子,比如火车的栈,就是车头先进入,但是出来的时候却是车尾先出来,车头最后出。,7.1.1 堆和栈的区别,2堆 堆(heap)一般位于bss段和
45、栈之间,用来动态分配内存。这段区域由程序员管理,程序员利用操作系统提供的分配和释放函数使用堆区的内存。如果程序员在堆上分配了一段内存,却没有释放,在目前主流的操作系统上,退出时会被操作系统释放。但是这并不是一个好的习惯,因为堆区的空间不是无限的,过多姆峙浠岬贾露涯诖嬉绯觯绦蛞斐踔帘览! 堆的管理与栈不同,操作系统在堆空间维护一个链表(请参考数据结构相关定义),每次程序员从堆分配内存的时候操作系统会从堆区扫描未用空间,当一个空间的大小符合申请空间的时候,就把此空间返回给程序员,同时会把申请的空间加入链表;当程序员释放一个空间的时候,操作系统会从堆的链表中删除指定的节点,并且把释放的空间放回未用空
46、间。,7.1.2 内存管理函数malloc()和free(),C程序有两个主要的内存管理函数:malloc()函数负责分配内存;free()函数释放malloc()分配的内存。这两个函数都是C标准库stdlib.h头文件定义的,Linux系统函数原型: void *malloc(size_t size); void free(void *ptr);,7.1.3 实用的内存分配函数calloc()和realloc(),在C程序开发项目中,还有两个实用的内存分配函数:calloc()用来分配一块新内存;realloc()用来改变一块已经分配的内存的大小。这两个函数都是在C标准库的stdlib.h头
47、文件定义的。 1calloc()函数 2realloc()函数,7.1.4 内存管理编程实例,本节给出一个内存管理编程实例。该实例代码展示了malloc()函数,calloc()函数分配内存空间写入字符串,之后使用realloc()函数重新分配内存空间,最后释放动态分配的内存。程序在分配的内存空间内写入字符串,通过打印字符串到屏幕展示内存分配的结果。,7.2 ANSI C文件管理,本节重点讲解ANSI C文件库。包括文件指针的概念;文件和流之间的关系;文本和二进制文件;和文件的基本操作。ANSI的C标准文件库封装了文件的系统调用,为了提高效率还加入了文件缓冲机制,提供记录的方式读写文件,并且具
48、有良好的可移植性和健壮性,是Linux C语言最基本的文件编程。,7.2.1 文件指针和流,文件是可以永久存储的,有特定顺序的一个有序,有名称的字节组成的集合。在Linux系统中,通常能见到的目录、设备文件和管道等,都属于文件,具有不同的特性。本节描述的ANSI文件只能用于普通文件操作。 ANSI文件操作提供了一个重要的结构-文件指针FIL。文件的打开、读写和关闭以及其他访问都要通过文件指针完成。FILE结构通常作为FILE*的方式使用,因此被称作文件指针,这个结构在stdio.h头文件的定义: typedef struct int level; unsigned flags; char fd
49、; unsigned char hold; int bsize; unsigned char _FAR *buffer; unsigned char _FAR *curp; unsigned istemp; short token; FILE;,7.2.2 存储方式,ANSI C规定了两种文件的存储方式:文本方式和二进制方式。文本文件也称作ASCII文件,每个自己存储一个ASCII码字符,文本文件存储量大,便于对字符操作,但是操作速度慢;二进制文件降数据按照内存中的存储形式存放,二进制文件的存储量小,存取速度快,适合存放中间结果。 在Linux系统上,文件的存放都是按照二进制方式存储的,用户在打开的时候,根据用户指定的打开方式进行存取。,7.2.3 标准输入,标准输入和标准错误,Linux系统为每个进程定义了标准输入、标准输出和标准错误三个文件流,也称作I/O数据流。系统预定义的三个文件流有固定的名称,因此无需创建可以直接使用。stdin是标准输入,默认是从键盘读取数据;stdout是标准输出,默认向屏幕输出数据;stderr是标准错误,默认是向屏幕输出数据。 三个I/O数据流定义在stdio.h头文件里,程序在使用前需要引用相关头文件。C标准库函数printf()默认使用stdout输出数据,用户也可以通过重新设置标准I/O,把程序的输入输出