Chap5-嵌入式Linux应用程序开发(ref)教学课件

上传人:风*** 文档编号:240746201 上传时间:2024-05-04 格式:PPT 页数:62 大小:1.36MB
返回 下载 相关 举报
Chap5-嵌入式Linux应用程序开发(ref)教学课件_第1页
第1页 / 共62页
Chap5-嵌入式Linux应用程序开发(ref)教学课件_第2页
第2页 / 共62页
Chap5-嵌入式Linux应用程序开发(ref)教学课件_第3页
第3页 / 共62页
点击查看更多>>
资源描述
Chap5嵌入式Linux应用程序开发(ref)11、获得的成功越大,就越令人高兴。野心是使人勤奋的原因,节制使人枯萎。12、不问收获,只问耕耘。如同种树,先有根茎,再有枝叶,尔后花实,好好劳动,不要想太多,那样只会使人胆孝懒惰,因为不实践,甚至不接触社会,难道你是野人。(名言网)13、不怕,不悔(虽然只有四个字,但常看常新。14、我在心里默默地为每一个人祝福。我爱自己,我用清洁与节制来珍惜我的身体,我用智慧和知识充实我的头脑。15、这世上的一切都借希望而完成。农夫不会播下一粒玉米,如果他不曾希望它长成种籽;单身汉不会娶妻,如果他不曾希望有小孩;商人或手艺人不会工作,如果他不曾希望因此而有收益。-马钉路德。(5)第二次编译gcc。运行configure,参数设置为-prefix=$PREFIX-target=arm-linux-enable-languages=c,c+。运行makeinstall。到此为止整个交叉编译环境就完全生成了。建立一个交叉编译工具链是一个相当复杂的过程,为了节省时间,网上有一些编译好的可用的交叉编译工具链可以下载。本书所附光盘也带有编译好的交叉编译工具链arm-linux-toolchains.tgz,只需简单地解压缩即可使用:tarxvzfarm-linux-toolchains.tgzC/arm9假设工具链解压缩到目录/arm9。解压完毕后把工具链目录加入到环境变量PATH中即可。交叉编译工具做完后,简单验证一下。首先用文字输入软件建立一个helloworld.c文件:#includeintmain(void)printf(helloworldn);return0;然后在命令行执行:$arm-linux-gcchelloworld.c-ohelloworld$filehelloworld如果输出以下信息,说明成功建立了编译工具。helloworld:ELF32-bitLSBexecutable,ARM,version1,dynamicallylinked(usessharedlibs),notstripped5.2 Linux及开发工具的使用GNU提供的编译工具包括汇编器as、C编译器gcc、C+编译器g+、链接器ld和二进制转换工具objcopy。基于ARM平台的工具分别为arm-linux-as、arm-linux-gcc、arm-linux-g+、arm-linux-ld和arm-linux-objcopy。GNU的所有开发工具都可以从gnu.org上下载,基于ARM的工具可以从uclinux.org获得。GNU的编译器功能非常强大,共有上百个操作选项,这也是这类工具让初学者头痛的原因。不过,实际开发中只需要用到有限的几个,大部分可以采用默认选项。GNU工具的开发流程如下:编写C、C+语言或汇编源程序,用gcc或g+生成目标文件,编写链接脚本文件,用链接器生成最终目标文件(elf格式),用二进制转换工具生成可下载的二进制代码。Linux下的GNU调试工具主要是gdb、gdbserver和kgdb。其中gdb和gdbserver可完成对目标板上Linux应用程序的远程调试。gdbserver是一个很小的应用程序,运行于目标板上,可监控被调试进程的运行,并通过串口与上位机上的gdb通信。开发者可以通过上位机的gdb输入命令,控制目标板上进程的运行,查看内存和寄存器的内容。gdb5.1.1以后的版本加入了对ARM处理器的支持,在初始化时加入-target=arm参数可直接生成基于ARM平台的gdbserver。gdb工具可以从ftp:/ftp.gnu.org/pub/gnu/gdb/上下载 Linux常用命令 用户在命令行输入命令后,由外壳进行解释。外壳是一种命令解释器,提供了用户和操作系统之间的交互接口。外壳是面向命令行的,而XWindow则是图形界面。外壳解释的命令送往操作系统执行。外壳可以执行Linux的系统内部命令,也可以执行应用程序。用户还可以利用外壳编程,执行复杂的命令程序。Linux提供几种外壳程序以供选择。常用的有Bourne外壳、C外壳和Korn外壳。各个外壳都能提供基本的功能,又有其各自的特点。Bourne外壳是由StevenBourne编写的,是UNIX的默认外壳。Bourne外壳的外壳编程能力很强,但是不能处理命令的用户交互特征,bash是Bourne外壳的增强版。C外壳是由加利福尼亚大学伯克利分校的BillJoy编写的。能提供Bourne外壳所不能处理的用户交互特征,如命令补全、命令别名、历史命令替换等。C外壳的编程能力不如Bourne外壳,但由于它的语法和C语言类似,所以C程序员将发现C外壳很顺手。Korn外壳是由DaveKorn编写的。Korn外壳融合了C外壳和Bourne外壳的优点,并与Bourne外壳完全兼容。Korn外壳的效率很高,其命令交互界面和编程交互界面都很不错。Bash是大多数Linux系统的默认外壳。其克服了Bourne外壳的缺点,又和Bourne外壳完全兼容。1登录和退出Linux启动后,给出login命令,等待用户登录。Login:Password:使用logout命令退出外壳。2更改账号密码使用passwd命令来设置新用户的口令。在设置口令之后,账号即能正常工作。语法:passwdOldpassword:Newpassword:Retypenewpassword:3联机帮助系统上几乎每条命令都带有相关的Manpage。在有困难时,可以立刻找到文件。语法:man命令例如,如果使用ls命令时遇到困难,可以输入:manls4远程登录用来连接到其他机器执行工作。在Linux上,由于对TCP/IP协议的完全支持,用户可以很容易的从Linux主机连接其他的计算机系统。语法:rlogin主机名-l用户名例如:rlogindoc-luser使用user账号登录到工作站doc中。语法:telnet主机名或telnetIP地址例如:telnet140.109.20.2515列出文件或目录语法:ls-atFlgRname其中name是文件名或目录名。ls命令用来浏览文件与目录,对于每个目录,该命令将列出其中所有的子目录与文件。6改变工作目录语法:cdname其中name是目录名、路径或目录缩写。cd除了有切换目录的功能外,还有一个功能就是,不管在哪个目录内,只要输入cd命令,不加任何参数,即可回到用户目录内。7复制文件语法:cp-r源地址目的地址带目录的拷贝,相当于DOS内的xcopy。8移动或更改文件、目录名称语法:mv源地址目的地址可以为文件或目录改名,也可以将文件由一个目录移入另一个目录。9建立新目录语法:mkdir目录名10删除目录语法:rmdir目录名或rm目录名11删除文件语法:rm文件名12列出当前所在的目录位置语法:pwd13查看文件内容语法:cat文件名14分页查看文件内容语法:more文件名或cat文件名|more15查看目录所占磁盘容量语法:du-s目录16文件传输(1)拷贝文件或目录至远程工作站。语法:rcp-r源地址目的主机名:目的地址。(2)自远程工作站拷贝文件或目录。语法:rcp-r源主机名:源地址目的地址。(3)本地工作站与远程工作站之间的文件传输,必须拥有远程工作站的账号及密码,才可进行传输工作。语法:ftp主机名或ftpip地址。17文件权限的设定(1)改变文件或目录的读、写、执行权限。语法:chmod-Rmodenamename:文件名或目录名。mode:3位8进制数字或rwx的组合。r-read(读),wwrite(写),xexecute(执行),uuser(当前用户),g-group(组),o-other(其他用户)。(2)改变文件或目录的所有权。语法:chown-R用户名name18检查自己所属的工作组名称语法:groups19改变文件或目录工作组所有权语法:chgrp-R工作组名name20改变文件或目录的最后修改时间语法:touchname21文件的链接同一文件,可拥有一个以上的名称,也就是把一个文件进行链接。语法:ln老文件名新文件名22文件中字符串的查找语法:grepstringfile23查寻文件或命令的路径语法:whereiscommand显示命令的路径。语法:whichcommand显示命令的路径,及使用者所定义的别名。语法:whatiscommand显示命令功能的摘要。语法:findsearch-path-namefilename-print搜寻指定路径下某文件的路径。24比较文件或目录的内容语法:diff-rname1name225文件打印输出用户可用.login文件中的setenvPRINTER命令来设定打印机名。26一般文件的打印语法:lpr-P打印机名文件名27ptroff文件的打印语法:ptroff-P打印机名-man-ms文件名28打印机控制命令(1)检查打印机状态、打印作业顺序号和用户名。语法:lpq-P打印机名(2)删除打印机内的打印作业(用户仅可删除自己的打印作业)。语法:lprm-P打印机名用户名或作业编号29进程控制(1)查看系统中的进程。语法:ps-aux(2)结束或终止进程。语法:kill-9PIDPID:利用ps命令所查出的进程号。(3)在后台执行进程的方式。语法:命令&(4)查看正在后台中执行的进程。语法:jobs(5)结束或终止后台中的进程。语法:kill%nn:利用jobs命令查看出的后台作业号30外壳变量(1)查看外壳变量的设定值。语法:set查看所有外壳变量的设定值。语法:echo$变量名显示指定的外壳变量的设定值。(2)设定外壳变量。语法:setvar=value(3)删除外壳变量。语法:unsetvar31环境变量(1)查看环境变量的设定值。语法:setenv查看所有环境变量的设定值。语法:echo$NAME显示指定的环境变量NAME的设定值。(2)设定环境变量。语法:setenvNAMEword(3)删除环境变量。语法:unsetenvNAME32别名(1)查看所定义的命令的别名语法:alias查看自己目前定义的所有命令,以及所对应的别名。语法:aliasname查看指定的name命令的别名。(2)定义命令的别名。语法:aliasnamecommandline(3)删除所定义的别名。语法:unaliasname33历史命令(1)设定命令记录表的长度。语法:sethistory=n(2)查看命令记录表的内容。语法:history(3)使用命令记录表。语法:!重复执行前一个命令。语法:!nn:命令记录表的命令编号。语法:!string重复前面执行过的以string为起始字符串的命令。(4)显示前一个命令的内容。语法:!:p(5)更改前一个命令的内容并执行。语法:oldstringnewstring将前一个命令中oldstring的部分改成newstring并执行。34文件的压缩(1)压缩文件。语法:compress文件名压缩文件语法:compressdir目录名压缩目录(2)解压缩文件。语法:uncompress文件名解压缩文件语法:uncompressdir目录名解压缩目录35管道命令的使用语法:命令1|命令2将命令1的执行结果送到命令2,作为命令2的输入。36输入/输出控制(1)标准输入的控制。语法:命令文件将文件作为命令的输入。例如:mail-smailtestweisongzhouhotmail文件将命令的执行结果送至指定的文件中。例如:ls-llist将执行“ls-l”命令的结果写入文件list中。37查看系统中的用户语法:who或finger语法:w语法:finger用户名或finger用户名域名38改变用户名语法:su用户名例如:suuser进入用户user的账号,passwrod:39查看用户名语法:whoami查看登录时的用户名。语法:whoami查看当前的用户名。若已执行过su命令,则显示出此用户的用户名。40检查远程系统是否正常语法:ping主机名或pingIP地址例如:pingdocgcc编译器的使用 gcc最基本的用法是:gccoptionsfile.其中的option是以“-”开始的各种选项,file是相关的文件名。在使用gcc的时候,必须要给出必要的选项和文件名。gcc的整个编译过程分别是:预处理,编译,汇编和链接。gcc编译器几个最常用的选项:-o表示要求编译器生成指定文件名的可执行文件;-c表示只要求编译器进行编译,而不要进行链接,生成以源文件的文件名命名但把其后缀由.c或变成.o的目标文件;-g要求编译器在编译的时候提供以后对程序进行调试的信息;-E表示编译器对源文件只进行预处理就停止,而不做编译、汇编和链接;-S表示编译器只进行编译,而不做汇编和链接;-O是编译器对程序提供的编译优化选项,在编译的时候使用该选项,可以使生成的执行文件的执行效率提高;-Wall指定产生全部的警告信息。$gcc-ohellohello.cgcc编译器就会生成一个hello的可执行文件。在hello.c的当前目录下执行./hello就可以看到程序的输出结果,在屏幕上打印出“Hellotheworld”的字符串来。GNU编译器生成的目标文件默认格式为elf(executivelinkedfile)格式,这是Linux系统所采用的可执行链接文件的通用文件格式。elf格式由若干个段(section)组成,如果没有特别指明,由标准c源代码生成的目标文件中包含以下段:.text(正文段)包含程序的指令代码,.data(数据段)包含固定的数据,如常量,字符串等,.bss(未初始化数据段)包含未初始化的变量和数组等。Makefile文件和Make命令 Makefile文件描述了目标文件之间的依赖关系,以及指定编译过程中使用的工具。一个工程中的源文件不计其数,按其类型、功能、模块分别放在若干个目录中。Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。Makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。Makefile带来的好处就是“自动化编译”,一旦写好,只需要一个Make命令,整个工程完全自动编译,极大地提高了软件开发的效率。Makefile的作用是根据配置的情况,构造出需要编译的源文件列表,然后分别编译,并把目标代码链接到一起,最终形成可执行的二进制文件。Makefile中一般包含如下内容:需要由make工具创建的项目,通常是目标(target)文件和可执行文件。要创建的项目依赖于哪些文件。创建每个项目时需要运行的命令。例如:example.o:example.cexample.hg+-c-gexample.c从上面的例子可以看出,第一行指定example.o为目标,并且依赖于example.c和example.h文件。随后的行指定了如何从目标所依赖的文件建立目标。当example.c或example.h文件在编译之后又被修改,则make工具可自动重新编译example.o,如果在前后两次编译之间,example.c和example.h均没有被修改,而且example.o还存在的话,就没有必要重新编译。1Makefile中的变量顶层Makefile定义并向环境中输出了许多变量,为各个子目录下的Makefile传递一些信息。有些变量,比如,SUBDIRS,不仅在顶层Makefile中定义并且赋初值,而且在arch/arm/Makefile还做了扩充。常用的变量有以下几类:版本信息版本信息有VERSION、PATCHLEVEL、SUBLEVEL、EXTRAVERSION和KERNELRELEASE等变量,用来定义当前内核的版本。比如,VERSION=2,PATCHLEVEL=4,SUBLEVEL=18,EXTRAVERSION=-rmk7,共同构成内核的发行版本KERNELRELEASE:2.4.18-rmk7。CPU体系结构:ARCH在顶层Makefile的开头,用ARCH定义目标CPU的体系结构,比如,ARCH:=arm。许多子目录的Makefile中,要根据ARCH的定义选择编译源文件的列表。路径信息:TOPDIR和SUBDIRSTOPDIR定义了Linux内核源代码所在的根目录。例如,各个子目录下的Makefile通过$(TOPDIR)/Rules.make就可以找到Rules.make的位置。SUBDIRS定义了一个目录列表,在编译内核或模块时,顶层Makefile就是根据SUBDIRS来决定进入哪些子目录。SUBDIRS的值取决于内核的配置,在顶层Makefile中SUBDIRS赋值为kerneldriversmmfsnetipclib;根据内核的配置情况,在arch/*/Makefile中扩充了SUBDIRS的值,可参考arch/arm/Makefile的例子。内核组成信息:HEAD,CORE_FILES,NETWORKS,DRIVERS,LIBS。Linux内核文件vmlinux是由以下规则产生的:vmlinux:$(CONFIGURATION)init/main.oinit/version.olinuxsubdirs$(LD)$(LINKFLAGS)$(HEAD)init/main.oinit/version.o-start-group$(CORE_FILES)$(DRIVERS)$(NETWORKS)$(LIBS)-end-group-ovmlinux可以看出,vmlinux是由HEAD、main.o、version.o、CORE_FILES、DRIVERS、NETWORKS和LIBS组成的。这些变量(如HEAD)都是用来定义链接生成vmlinux所需的目标文件和库文件列表。其中,HEAD在arch/arm/Makefile中定义,用来确定最先链接进vmlinux的文件列表。比如,对于ARM系列HEAD的定义为:HEAD:=arch/arm/kernel/head-$(PROCESSOR).oarch/arm/kernel/init_task.o表明head-$(PROCESSOR).o和init_task.o需要最先被链接到vmlinux中。PROCESSOR为armv或armo,取决于目标CPU。编译信息:CPP,CC,AS,LD,AR,CFLAGS,LINKFLAGS在Rules.make中定义的是编译的通用规则,具体到特定的场合,需要明确给出编译环境,编译环境就是在以上的变量中定义的。针对交叉编译的要求,定义了CROSS_COMPILE。比如:CROSS_COMPILE=arm-linux-CC=$(CROSS_COMPILE)gccLD=$(CROSS_COMPILE)ld.由于CROSS_COMPILE定义了交叉编译器前缀arm-linux-,表明所有的交叉编译工具都是以arm-linux-开头的,所以在各个交叉编译器工具之前,都加入了$(CROSS_COMPILE),以组成一个完整的交叉编译工具文件名,比如,arm-linux-gcc。CFLAGS定义了传递给C编译器的参数。LINKFLAGS是链接生成vmlinux时,由链接器使用的参数。LINKFLAGS在arm/*/Makefile中定义,比如:#arch/arm/MakefileLINKFLAGS:=-p-X-Tarch/arm/vmlinux.lds配置变量CONFIG_*.config文件中有许多的配置变量等式,用来说明用户配置的结果。例如,CONFIG_MODULES=y表明用户选择了Linux内核的模块功能。.config被顶层Makefile包含后,就形成许多的配置变量,每个配置变量具有确定的值:y表示本编译选项对应的内核代码被静态编译进Linux内核;m表示本编译选项对应的内核代码被编译成模块;n表示不选择此编译选项;如果没有赋值,那么配置变量的值为空。2Rules.make变量Rules.make定义了所有Makefile共用的编译规则。Linux把共用的编译规则统一放置到Rules.make中,并在各自的Makefile中通过语句“includeRules.make”包含Rules.make。这样就避免了在多个Makefile中重复同样的规则。Rules.make文件定义了许多变量,最为重要的是编译、链接列表变量。O_OBJS、L_OBJS、OX_OBJS和LX_OBJS:这些变量代表的是本级目录下需要编译进Linux内核vmlinux的目标文件列表,其中OX_OBJS和LX_OBJS中的“X”表明目标文件使用了EXPORT_SYMBOL输出符号。M_OBJS和MX_OBJS:定义本级目录下需要被编译成可装载模块的目标文件列表。同样,MX_OBJS中的“X”表明目标文件使用了EXPORT_SYMBOL输出符号。O_TARGET和L_TARGET:每个子目录下都有一个O_TARGET或L_TARGET,Rules.make首先从源代码编译生成O_OBJS和OX_OBJS中所有的目标文件,然后使用$(LD)-r把它们链接成一个O_TARGET或L_TARGET。O_TARGET以.o结尾,而L_TARGET以.a结尾。3子目录Makefile子目录Makefile用来控制本级目录下源代码的编译规则。#Makefileforthelinuxkernel.#Allofthe(potential)objectsthatexportsymbols.#Thislistcomesfromgrep-lEXPORT_SYMBOL*.hc.export-objs:=tc.o#Objectfilelists.obj-y:=obj-m:=obj-n:=obj-:=obj-$(CONFIG_TC)+=tc.oobj-$(CONFIG_ZS)+=zs.oobj-$(CONFIG_VT)+=lk201.olk201-map.olk201-remap.o#Filesthatarebothresidentandmodular:removefrommodular.obj-m:=$(filter-out$(obj-y),$(obj-m)#TranslatetoRules.makelists.L_TARGET:=tc.aL_OBJS:=$(sort$(filter-out$(export-objs),$(obj-y)LX_OBJS:=$(sort$(filter$(export-objs),$(obj-y)M_OBJS:=$(sort$(filter-out$(export-objs),$(obj-m)MX_OBJS:=$(sort$(filter$(export-objs),$(obj-m)include$(TOPDIR)/Rules.make4makemake是一个命令工具,是一个解释Makefile中指令的命令工具。一般来说,大多数的IDE都有这个命令,比如:Delphi的make,VisualC+的nmake,以及Linux下GNU的make。make命令执行时,需要一个Makefile文件,以告诉make命令怎么去编译和链接程序。一般来说,最简单的就是直接在命令行下输入make命令,make命令会找当前目录的Makefile来执行,一切都是自动的。GNU的make工作时的执行步骤入下:(1)读入所有的Makefile。(2)读入被include的其他Makefile。(3)初始化文件中的变量。(4)推导隐含规则,并分析所有规则。(5)为所有的目标文件创建依赖关系链。(6)根据依赖关系,决定哪些目标要重新生成。(7)执行生成命令。15步为第一个阶段,67步为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是拖延战术,如果变量出现在依赖关系的规则中,那么仅当这条依赖关系被决定要使用了,变量才会在其内部展开。配置文件 在Linux内核中,配置命令有多种方式:MakeconfigMakeoldconfigscripts/ConfigureMakemenuconfigscripts/MenuconfigMakexconfigscripts/tkparse以字符界面配置(makeconfig)为例,顶层Makefile调用scripts/Configure,按照arch/arm/config.in来进行配置。命令执行完后产生文件.config,其中保存着配置信息。下一次再做makeconfig将产生新的.config文件,原.config被改名为.config.old。下面对配置文件所支持的配置语句做简要的说明。1顶层菜单mainmenu_name/prompt/prompt/其中/prompt/是一串提示符,mainmenu_name设置最高层菜单的名字,只在makexconfig时才会显示。2询问语句bool/prompt/symbol/hex/prompt/symbol/word/int/prompt/symbol/word/string/prompt/symbol/word/tristate/prompt/symbol/询问语句首先显示一串提示符/prompt/,等待用户输入,并把输入的结果赋给/symbol/所代表的配置变量。不同的询问语句的区别在于它们接受的输入数据类型不同,比如,bool接受布尔类型(y或n),hex接受16进制数据。有些询问语句还有第三个参数/word/,用来给出默认值。3定义语句define_bool/symbol/word/define_hex/symbol/word/define_int/symbol/word/define_string/symbol/word/define_tristate/symbol/word/不同于询问语句的等待用户输入,定义语句显式的给配置变量/symbol/赋值/word/。4依赖语句dep_bool/prompt/symbol/dep/.dep_mbool/prompt/symbol/dep/.dep_hex/prompt/symbol/word/dep/.dep_int/prompt/symbol/word/dep/.dep_string/prompt/symbol/word/dep/.dep_tristate/prompt/symbol/dep/.与询问语句类似,依赖语句也是定义新的配置变量。不同的是,配置变量/symbol/的取值将依赖于配置变量列表/dep/。这就意味着,被定义的配置变量所对应功能的取舍取决于依赖列表所对应功能的选择。5选择语句choice/prompt/word/word/choice语句首先给出一串选择列表,供用户选择其中一种。比如,LinuxforARM支持多种基于ARM核的CPU,Linux使用choice语句提供一个CPU列表,供用户选择:choiceARMsystemtypeAnakinCONFIG_ARCH_ANAKINSA1100-basedCONFIG_ARCH_SA11006if语句if/expr/then/statement/.fiif/expr/then/statement/.else/statement/.fiif语句对配置变量进行判断,并做出不同的处理。判断条件/expr/可以是单个配置变量或字符串,也可以是带操作符的表达式。操作符有:=,!=,-o,-a等。7菜单块(menublock)语句mainmenu_optionnext_commentcomment.endmenu8Source语句source/word/word/是文件名,source的作用是调入新的文件。Vi编辑器的使用 1工作模式Vi是“Visualinterface”的简称,可以执行输出、删除、查找、替换、块操作等众多文本操作,而且用户可以根据自己的需要对其进行定制。Vi有三种基本工作模式:命令行模式、文本输入模式和末行模式。命令行模式任何时候,不管用户处于何种模式,只要按一下键,即可使Vi进入命令行模式;我们在shell环境(提示符为$)下输入启动命令“vi”,进入编辑器时,也是处于该模式下。在该模式下,用户可以输入各种合法的Vi命令,用于管理自己的文档。此时从键盘上输入的任何字符都被当做编辑命令来解释,若输入的字符是合法的Vi命令,则Vi在接受用户命令之后完成相应的动作。但需注意的是,所输入的命令并不在屏幕上显示出来。若输入的字符不是Vi的合法命令,Vi会响铃报警。文本输入模式在命令模式下输入插入命令i、附加命令a、打开命令o、修改命令c、取代命令r或替换命令s都可以进入文本输入模式。在该模式下,用户输入的任何字符都被Vi当做文件内容保存起来,并将其显示在屏幕上。在文本输入过程中,若想回到命令模式下,按Esc键即可。末行模式在命令模式下,用户按“:”键即可进入末行模式下,此时Vi会在显示窗口的最后一行,显示一个“:”作为末行模式的提示符,等待用户输入命令。多数文件管理命令都是在此模式下执行的。末行命令执行完后,Vi自动回到命令模式。2进入在提示符“$”后键入Vi和想要编辑的文件名,便可进入Vi。例如:$viexample.c如果只键入Vi,而不带文件名,也可以进入Vi,之后在光标处键入文件内容。进入Vi后,首先进入的就是命令模式,进入Vi时,用户不仅可以指定一个待编辑的文件名,而且还有许多附加操作。如果希望在进入Vi之后,光标处于文件中特定的某行上,可在Vi后加上选项+n,其中n为指定的行数。例如:$vi+5example1.c3退出在命令模式中,连按两次大写字母Z,若当前编辑的文件曾被修改过,则Vi保存该文件后退出,返回到shell;若当前编辑的文件没被修改过,则Vi直接退出,返回到shell。在末行模式下,输入命令::wVi保存当前编辑文件,但并不退出,而是继续等待用户输入命令。在使用w命令时,可以再给编辑文件起一个新的文件名。:wnewfile此时Vi将把当前文件的内容保存到指定的newfile中,而原有文件保持不变。在末行模式下,输入命令::q系统退出Vi返回到shell。若在用此命令退出Vi时,编辑文件没有被保存,则Vi在显示窗口的最末行显示如下信息:Nowritesincelastchange(use!tooverrides)提示用户该文件被修改后没有保存,然后Vi并不退出,继续等待用户命令。若用户就是不想保存被修改后的文件而要强行退出Vi时,可使用命令::q!Linux下C语言编程 1文件读写当需要打开一个文件进行读写操作的时候,可以使用系统调用函数open。文件操作完成后,调用close函数关闭文件。intopen(constchar*pathname,intflags);intopen(constchar*pathname,intflags,mode_tmode);intclose(intfd);open函数有两个形式,在此只介绍第一种方式。其中pathname是我们要打开的文件名,包含路径名称,默认是在当前路径下。Flags取值可以是下面的一个值或者是几个值的组合。O_RDONLY:以只读的方式打开文件;O_WRONLY:以只写的方式打开文件;O_RDWR:以读写的方式打开文件;O_APPEND:以追加的方式打开文件;O_CREAT:创建一个文件;要采用open的第二种形式;O_EXEC:使用该选项时,如果使用了O_CREAT而且文件已经存在,就会发生一个错误;O_NOBLOCK:以非阻塞的方式打开一个文件;O_TRUNC:如果文件已经存在,则删除文件的内容。如果打开文件成功,open会返回一个文件描述符。以后对文件的所有操作就可以对这个文件描述符进行操作了。当操作完成以后,要关闭文件时,只要调用close就可以了,其中fd是要关闭的文件描述符。文件打开后,就可以调用函数read和write进行文件的读写。ssize_tread(intfd,void*buffer,size_tcount);ssize_twrite(intfd,constvoid*buffer,size_tcount);fd是要进行读写操作的文件描述符,buffer是要写入文件内容或读出文件内容的内存地址,count是要读写的字节数。对于普通的文件,read从指定的文件(fd)中读取count个字节到buffer缓冲区中,同时返回count。如果read读到了文件的结尾或者被一个信号所中断,返回值会小于count。如果是由信号中断引起返回,而且没有读出数据,read会返回1,且设置errno为EINTR。当程序读到了文件结尾的时候,read会返回0。write从buffer中写count字节到文件fd中,成功时返回实际所写的字节数。#defineBUFFER_SIZE1024intmain(intargc,char*argv)intfrom_fd,to_fd;intbytes_read,bytes_write;charbufferBUFFER_SIZE;char*ptr;if(argc!=3)fprintf(stderr,Usage:%sfromfiletofilea,argv0);exit(1);if(from_fd=open(argv1,O_RDONLY)=-1)fprintf(stderr,Open%sError:%s,argv1,strerror(errno);exit(1);if(to_fd=open(argv2,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)=-1)fprintf(stderr,Open%sError:%s,argv2,strerror(errno);exit(1);while(bytes_read=read(from_fd,buffer,BUFFER_SIZE)if(bytes_read=-1)&(errno!=EINTR)break;elseif(bytes_read0)ptr=buffer;while(bytes_write=write(to_fd,ptr,bytes_read)if(bytes_write=-1)&(errno!=EINTR)break;elseif(bytes_write=bytes_read)break;elseif(bytes_write0)ptr+=bytes_write;bytes_read-=bytes_write;if(bytes_write=-1)break;close(from_fd);close(to_fd);exit(0);2文件属性文件具有各种各样的属性,除了上面提到的文件权限以外,文件还有创建时间、大小等属性。有时候要判断文件是否可以进行某种操作,此时可以使用access函数。intaccess(constchar*pathname,intmode);其中,pathname是文件名称,mode是所要判断的属性。可以取以下值或者是其组合:R_OK文件可以读;W_OK文件可以写;X_OK文件可以执行;F_OK文件存在。当测试成功时,函数返回0;如果有一个条件不符时,返回1。如果要获得文件的其他属性,可以使用函数stat或者fstat。intstat(constchar*file_name,structstat*buf);intfstat(intfiledes,structstat*buf);structstatdev_tst_dev;/*设备*/ino_tst_ino;/*节点*/mode_tst_mode;/*模式*/nlink_tst_nlink;/*硬连接*/uid_tst_uid;/*用户ID*/gid_tst_gid;/*组ID*/dev_tst_rdev;/*设备类型*/off_tst_off;/*文件字节数*/unsignedlongst_blksize;/*块大小*/unsignedlongst_blocks;/*块数*/time_tst_atime;/*最后一次访问时间*/time_tst_mtime;/*最后一次修改时间*/time_tst_ctime;/*最后一次改变时间(指属性)*/;stat用来判断没有打开的文件,而fstat用来判断打开的文件。使用最多的属性一般是st_mode,通过该属性可以判断给定的文件是一个普通文件,还是一个目录或者连接。可以使用下面几个宏来判断:S_ISLNK(st_mode),是否是一个连接;S_ISREG,是否是一个常规文件;S_ISDIR,是否是一个目录;S_ISCHR,是否是一个字符设备;S_ISBLK,是否是一个块设备;S_ISFIFO,是否是一个FIFO文件;S_ISSOCK,是否是一个SOCKET文件。3目录文件的操作在编写程序的时候,有时候想得到当前的工作路径。C库函数提供了getcwd来解决这个问题:char*getcwd(char*buffer,size_tsize);如果提供一个size大小的buffer,getcwd会把当前的路径拷贝到buffer中,如果buffer太小,函数会返回1和一个错误号。Linux提供了大量的目录操作函数,下面列出了几个比较简单和常用的函数:intmkdir(constchar*path,mode_tmode);DIR*opendir(constchar*path);structdirent*readdir(DIR*dir);voidrewinddir(DIR*dir);intclosedir(DIR*dir);mkdir就是创建一个目录,opendir打开一个目录为以后读做准备,readdir读一个打开的目录,rewinddir是用来重读目录的,closedir是关闭一个目录。下面的程序有一个输入参数,如果这个参数是一个文件名,输出这个文件的大小和最后修改的时间;如果是一个目录,输出这个目录下所有文件的大小和修改时间。staticintget_file_size_time(constchar*filename)structstatstatbuf;if(stat(filename,&statbuf)=-1)printf(Getstaton%sError:%s,filename,strerror(errno);return(-1);if(S_ISDIR(statbuf.st_mode)return(1);if(S_ISREG(statbuf.st_mode)printf(%ssize:%ldbytesmodifiedat%s,filename,statbuf.st_size,ctime(&statbuf.st_mtime);return(0);intmain(intargc,char*argv)DIR*dirp;structdirent*direntp;intstats;if(argc!=2)printf(Usage:%sfilenamea,argv0);exit(1);if(stats=get_file_size_time(argv1)=0)|(stats=-1)exit(1);if(dirp=opendir(argv1)=NULL)printf(OpenDirectory%sError:%s,argv1,strerror(errno);exit(1);while(direntp=readdir(dirp)!=NULL)if(get_file_size_time(direntp-closedir(dirp);exit(1);5.3 引导程序的移植在掌握GNU开发工具后,就需要对系统的引导程序进行移植了。嵌入式的引导程序是与处理器体系结构紧密联系的,是嵌入式系统开发的难点之一,同时也是系统运行的一个基本前提条件,没有这段和硬件紧密相连的代码,多么精悍的内核也发挥不了作用。嵌入式Linux的引导机理分析 一个嵌入式软件系统通常可以分为引导程序BootLoader、操作系统内核、文件系统和用户应用程序4个层次。1BootLoader工作原理BootLoader是系统加电启动运行的第一段软件代码。通过PC的体系结构我们可以知道,PC机中的引导加载程序由BIOS(其本质就是一段固件程序)和位于硬盘MBR中的引导程序一起组成。BIOS在完成硬件检测和资源分配后,将硬盘MBR中的引导程序读到系统的RAM中,然后将控制权交给引导程序。引导程序的主要运行任务是将内核映像从硬盘上读到RAM中,然后跳转到内核的入口点去运行,也即开始启动操作系统。由于在嵌入式系统中,通常并没有像BIOS那样的固件程序(有的嵌入式系统也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。对于一个嵌入式系统来说,可能有的包括操作系统,有的小型系统也可以只包括应用程序,但是在这之前都需要BootLoader为它准备一个正确的环境。通常,BootLoader是依赖于硬件而实现的,特别是在嵌入式领域,为嵌入式系统建立一个通用的BootLoader是很困难的。但是可以归纳一些通用的概念出来,以便简化特定BootLoader的设计与实现。简单地说,BootLoader是在操作系统内核或用户应用程序运行之前运行的一段小程序。通过这段小程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,为最终调用操作系统内核或用户应用程序准备好正确的环境。2BootLoader的启动过程从操作系统的角度看,BootLoader的总目标就是正确地调用内核来执行。BootLoader的启动过程大多数分为阶段1和阶段2。阶段1主要包含依赖于CPU体系结构的硬件初始化代码,而且通常都是用汇编语言来实现的,以达到短小精悍的目的。这个阶段通常包括以下步骤:(1)硬件设备初始化。这是BootLoader开始就执行的操作,其目的是为阶段2的执行,以及随后内核的执行准备好基本的硬件环境。(2)为加载BootLoader的阶段2准备RAM空间。为了获得更快的执行速度,通常把阶段2加载到RAM空间来执行。(3)拷贝BootLoader阶段2的代码到RAM空间中。(4)设置好堆栈。(5)跳转到阶段2的C程序入口点。BootLoader的阶段2通常用C语言来实现,这样可以实现更复杂的功能,而且代码会具有更好的可读性和可移植性。通常包括以下步骤:(1)初始化本阶段要使用到的硬件设备。(2)检测系统内存映射。(3)将内核映像和根文件系统映像从Flash上读到RAM空间中。(4)为内核设置启动参数。(5)调用内核。3BootLoader代码分析下面对引导程序2410INIT.S进行分析,以加深对BootLoader的理解。在第一阶段完成依赖于体系结构硬件初始化的代码,包括禁止看门狗、禁止中断、初始化各控制寄存器拷贝自身到RAM等。IMPORTMainAREAInit,CODE,READONLYENTRYbResetHandlerResetHandlerldrr0,=WTCONldrr1,=0 x0strr1,r0ldrr0,=INTMSKldrr1,=0 xffffffffstrr1,r0ldrr0,=INTSUBMSKldrr1,=0 x7ffstrr1,r0ldrr0,=LOCKTIMEldrr1,=0 xffffffstrr1,r0ldrr0,=SMRDATAldrr1,=BWSCONaddr2,r0,#520ldrr3,r0,#4strr3,r1,#4cmpr2,r0bne%B0blInitStacksldrr0,=HandleIRQldrr1,=IsrIRQstrr1,r0;拷贝自身代码到RAMldrr0,=|Image$RO$Limit|;ldrr1,=|Image$RW$Base|;ldrr3,=|Image$ZI$Base|cmpr0,r1beq%F21cmpr1,r3ldrccr2,r0,#4strccr2,r1,#4bcc%B12ldrr1,=|Image$ZI$Limit|movr2,#03cmpr3,r1strccr2,r3,#4bcc%B3blMainb.END第二阶段通常用C语言实现,包括内存管理单元初始化、时钟设置、端口设置和串口初始化等。voidIsr_Init(void)rINTMOD=0 x0;/工作在IRQ模式rINTMSK=BIT_ALLMSK;/屏蔽中断rINTSUBMSK=BIT_SUB_ALLMSK;/屏蔽子中断voidMain(void)MMU_Init();/MMU初始化ChangeClockDivider(1,1);/设置时钟除法器-1:2:4ChangeMPllValue(0 xa1,0 x3,0 x1);/时钟值FCLK=202.8MHzPort_Init();Isr_Init();Uart_Init(0,115200);Uart_Select(0);while(1)Uart_Printf(nnSMDK2410Board(MCUS3C2410)ExampleProgramVer1.0(20020521)FCLK=%dHznn,FCLK);与一般的C语言程序一样,第二阶段程序从Main()函数开始。因为所采用的S3C2410X处理器内含存储器管理单元MMU,所以首先需要进行存储器管理单元的初始化。紧接着设置系统工作主时钟,若使用USB设备则USB时钟也需要做相应初始化。其次对端口工作状态进行设定。然后设定处理器工作模式,以及中断控制。最后初始化串口,与宿主机建立联系,以利于显示调试信息。启动成功后,可以执行主程序。VIVI简介 VIVI是韩国Mizi公司开发的BootLoader,可用于ARM9处理器的引导。VIVI利用串行通信为用户提供接口。为连接VIVI,首先利用串口电缆连接宿主机和目标板,然后在主机上运行串口通信程序,并在目标板上正确设置VIVI以支持串口。正确连接后,就可以由串口通信程序显示提示信息,提示信息的最后一行如下所示:PressReturntostarttheLINUXnow,anyotherkeyforvivi.VIVI也有前面说过的两种工作模式,启动模式可以在一段时间后自行启动Linux内核,这是VIVI的默认方式。出现上述信息后,如果按除回车键外的任意键,即可进入下载模式,出现“vivi”提示符。在下载模式下,VIVI为用户提供了一个命令行接口,通过该接口可以使用VIVI提供的一些命令。1load命令将二进制文件载入到Flash或者RAM,命令格式:load|其中命令行参数描述装载位置,有flash和ram两种选项;参数或描述装载的地址,如果有提前定义的mtd分区信息,可以只输入分区名称,否则需要指定地址和大小;参数确定文件的传输协议,常采用的选项“x”用来指定采用xmodem协议。例如:viviloadflashkernelx,装载压缩映像文件zImage到flash存储器中,地址是kernel分区,并采用xmodem传输协议。也可以指定地址和大小,例如:viviloadflash0 x800000 xc0000 x。2part命令操作MTD分区信息,比如,显示、增加、删除、复位、保存MTD分区等。partshow:显示mtd分区信息。partadd:增加新的mtd分区,其中为新mtd分区名称,是mtd器件的偏移,表示mtd分区的大小,表示分区类型,可选项有JFFS2、LOCKED和BONFS。partdel:删除一个mtd分区。partreset:恢复mtd分区为默认值。partsave:在flash中永久保存参数值和分区信息。3param命令用来设置或者察看参数。例如:改变“linuxcommandline”,使用viviparamsetlinux_cmd_lineyouwish.。也可以改变引导程序启动的时间,使用viviparamsetboot_delay100000实现。4boot命令用来引导存储在flash存储器或者ram中的linux内核。命令格式:boot|参数设定存储linux内
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 教学培训


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!