《嵌入式Linux操作系统》3 嵌入式Linux编程环境.pdf
《《嵌入式Linux操作系统》3 嵌入式Linux编程环境.pdf》由会员分享,可在线阅读,更多相关《《嵌入式Linux操作系统》3 嵌入式Linux编程环境.pdf(34页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、 华清远见嵌入式学院:www.embedu.org 华清远见嵌入式学院:www.embedu.org 嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org 第 3 章 嵌入式 Linux 编程环境 本章内容 本章内容包括常用的 Linux 开发工具使用技巧和 Linux 编程技术。本章内容比 Linux 编程方面的书籍简略得多,重点介绍常用的 Linux 编程工具和技巧。通过本章学习可以使读者快速掌握基本的 Linux 开发工具,为后续的嵌入式 Linux 开发打下基础。嵌入式 Linux 操作系统第 3 章 嵌入式 Linux
2、 编程环境 华清远见嵌入式学院:www.embedu.org 3.1 Linux 编辑器 vi 的使用 Linux 系统提供了一个完整的编辑器家族系列,如 ed、ex、vi 和 emacs 等。按功能它们可以分为两大类:行编辑器(ed、ex)和全屏幕编辑器(vi、emacs)。行编辑器每次只能对单行进行操作,使用起来很不方便。而全屏幕编辑器可以对整个屏幕进行编辑,用户编辑的文件直接显示在屏幕上,从而克服了行编辑的那种不直观的操作方式,便于用户学习和使用,具有强大的功能。vi 是 Linux 系统的第一个全屏幕交互式编辑程序,它从诞生至今一直得到广大用户的青睐,历经数十年仍然是人们主要使用的文本
3、编辑工具,足以见其生命力之强,而强大的生命力是其强大的功能带来的。由于大多数读者在此之前都已经用惯了 Windows 的 word 等编辑器,因此,在刚刚接触时总会或多或少不适应,但只要习惯之后,就能感受到它的方便与快捷。3.1.1 vi 的模式的模式 vi 有 3 种模式,分别为命令行模式、插入模式及底行模式各模式的功能,下面具体进行介绍。(1)命令行模式 用户在用 vi 编辑文件时,最初进入的为一般模式。在该模式中可以通过上下移动光标进行“删除字符”或“整行删除”等操作,也可以进行“复制”、“粘贴”等操作,但无法编辑文字。(2)插入模式 只有在该模式下,用户才能进行文字编辑输入,用户课按E
4、SC键回到命令行模式。(3)底行模式 在该模式下,光标位于屏幕的底行。用户可以进行文件保存或退出操作,也可以设置编辑环境,如寻找字符串、列出行号等。3.1.2 vi 的基本流程的基本流程(1)进入 vi,即在命令行下键入 vi hello(文件名)。此时进入的是命令行模式,光标位于屏幕的上方,如图 3.1 所示。(2)在命令行模式下键入 i 进入到插入模式,如图 3.2 所示。可以看出,在屏幕底部显示有“插入”表示插入模式,在该模式下可以输入文字信息。嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org 图 3.1 进入 vi
5、命令行模式 图 3.2 进入 vi 插入模式 嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org(3)最后,在插入模式中,输入“Esc”,则当前模式转入命令行模式,并在底行行中输入“:wq”(存盘退出)进入底行模式,如图 3.3 所示。这样,就完成了一个简单的 vi 操作流程:命令行模式插入模式底行模式。由于 vi 在不同的模式下有不同的操作功能,因此,读者一定要时刻注意屏幕最下方的提示,分清所在的模式。图 3.3 进入 Vi 底行模式 3.1.3 vi 的各模式功能键的各模式功能键(1)命令行模式常见功能键如表 3.1 所示
6、。表 3.1 vi 命令行模式功能键 目 录 目 录 内 容 I 切换到插入模式,此时光标当于开始输入文件处 A 切换到插入模式,并从目前光标所在位置的下一个位置开始输入文字 O 切换到插入模式,且从行首开始插入新的一行 ctrl+b 屏幕往“后”翻动一页 ctrl+f 屏幕往“前”翻动一页 ctrl+u 屏幕往“后”翻动半页 ctrl+d 屏幕往“前”翻动半页 0(数字 0)光标移到本行的开头 G 光标移动到文章的最后 嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org nG 光标移动到第 n 行$移动到光标所在行的“行尾”
7、n 光标向下移动 n 行/name 在光标之后查找一个名为 name 的字符串?name 在光标之前查找一个名为 name 的字符串 X 删除光标所在位置的“后面”一个字符 续表 目 录 目 录 内 容 X 删除光标所在位置的“前面”一个字符 dd 删除光标所在行 ndd 从光标所在行开始向下删除 n 行 yy 复制光标所在行 nyy 复制光标所在行开始的向下 n 行 p 将缓冲区内的字符粘贴到光标所在位置(与 yy搭配)U 恢复前一个动作 (2)插入模式的功能键只有一个,也就是 Esc 退出到命令行模式。(3)底行模式常见功能键如表 3.2 所示。表 3.2 vi 底行模式功能键 目 录 目
8、 录 内 容:w 将编辑的文件保存到磁盘中:q 退出 Vi(系统对做过修改的文件会给出提示):q!强制退出 Vi(对修改过的文件不作保存):wq 存盘后退出:w filename 另存一个命为 filename 的文件:set nu 显示行号,设定之后,会在每一行的前面显示对应行号:set nonu 取消行号显示 3.2 gcc 编译器编译器 GNU CC(简称为 Gcc)是 GNU 项目中符合 ANSI C 标准的编译系统,能够编译用 C、C+和 Object C 等语言编写的程序。gcc 不仅功能强大,而且可以编译如 C、C+、Object C、Java、Fortran、Pascal、Mo
9、dula-3 和 Ada 等多种语言,而且 gcc 又是一个交叉平台编译器,它能够在当前 CPU 平台上为多种不同体系结构的硬件平台开嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org 发软件,因此尤其适合在嵌入式领域的开发编译。本章中的示例,除非特别注明,否则均采用 gcc 版本为 4.0.0。下表 3.3 是 gcc 支持编译源文件的后缀及其解释。表 3.3 Gcc 所支持后缀名解释 后 缀 名 所对应的语言 后 缀 名 所对应的语言.c C 原始程序.s/.S 汇编语言原始程序.C/.cc/.cxx C+原始程序.h 预
10、处理文件(头文件).m Objective-C 原始程序.o 目标文件.i 已经过预处理的 C 原始程序.a/.so 编译后的库文件.ii 已经过预处理的 C+原始程序 3.2.1 gcc 编译流程解析编译流程解析 如本章开头提到的,gcc 的编译流程分为了 4 个步骤,分别为:预处理(Pre-Processing);编译(Compiling);汇编(Assembling);链接(Linking)。下面就具体来查看一下 gcc 是如何完成 4 个步骤的。首先,有以下 hello.c 源代码:#include int main()printf(Hello!This is our embedded
11、 world!n);return 0;(1)预处理阶段 在该阶段,编译器将上述代码中的 stdio.h 编译进来,并且用户可以使用 gcc 的选项“-E”进行查看,该选项的作用是让 gcc 在预处理结束后停止编译过程。rootlocalhost Gcc#gcc E hello.c o hello.i 在此处,选项“-o”是指目标文件,由表 3.3 可知,“.i”文件为已经过预处理的C 原始程序。以下列出了 hello.i 文件的部分内容:typedef int(*_gconv_trans_fct)(struct _gconv_step*,struct _gconv_step_data*,voi
12、d*,_const unsigned char*,_const unsigned char*,嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org _const unsigned char*,unsigned char*,size_t*);#2 hello.c 2 int main()printf(Hello!This is our embedded world!n);return 0;由此可见,Gcc 确实进行了预处理,它把“stdio.h”的内容插入到 hello.i 文件中。(2)编译阶段 接下来进行的是编译阶段,在这个阶
13、段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。rootlocalhost Gcc#gcc S hello.i o hello.s 以下列出了 hello.s 的内容,可见 gcc 已经将其转化为汇编了,感兴趣的读者可以分析一下这一行简单的 C 语言小程序是如何用汇编代码实现的。.file hello.c .section.rodata .align 4.LC0:.string Hello!This is our embedded wo
14、rld!.text.globl main .type main,function main:pushl%ebp movl%esp,%ebp subl$8,%esp andl$-16,%esp movl$0,%eax addl$15,%eax addl$15,%eax shrl$4,%eax sall$4,%eax 嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org subl%eax,%esp subl$12,%esp pushl$.LC0 call puts addl$16,%esp movl$0,%eax leave ret
15、 .size main,.-main .ident GCC:(GNU)4.0.0 20050519(Red Hat 4.0.0-8).section.note.GNU-stack,progbits (3)汇编阶段 汇编阶段是把编译阶段生成的“.s”文件转成目标文件,读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。如下所示:rootlocalhost Gcc#gcc c hello.s o hello.o (4)链接阶段 在成功编译之后,就进入了链接阶段。在这里涉及到一个重要的概念:函数库。读者可以重新查看这个小程序,在这个程序中并没有定义“printf”的函数实现
16、,且在预编译中包含进的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”。动态库与之相反,在编译链接时并没有
17、把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。rootlocalhost Gcc#gcc hello.o o hello 运行该可执行文件,出现正确的结果如下。rootlocalhost Gcc#./hello Hello!This is our embedded world!3.2.2 gcc 编译选项分析编译选项分析 嵌入式 Linux 操作系统第 3 章 嵌入式 Linux
18、编程环境 华清远见嵌入式学院:www.embedu.org gcc 有超过 100 个的可用选项,主要包括总体选项、告警和出错选项、优化选项和体系结构相关选项。以下对每一类中最常用的选项进行讲解。(1)总体选项 gcc 的总结选项如表 3.4 所示,很多在前面的示例中已经有所涉及。表 3.4 gcc 总体选项列表 后 缀 名 所对应的语言-c 只是编译不链接,生成目标文件“.o”-S 只是编译不汇编,生成汇编代码-E 只进行预编译,不做其他处理-g 在可执行程序中包含标准调试信息-o file 把输出文件输出到 file 里-v 打印出编译器内部编译各过程的命令行信息和编译器的版本-I dir
19、 在头文件的搜索路径列表中添加 dir 目录-L dir 在库文件的搜索路径列表中添加 dir 目录-static 链接静态库-llibrary 连接名为 library的库文件 对于“-c”、“-E”、“-o”、“-S”选项在前一小节中已经讲解了其使用方法,在此主要讲解另外两个非常常用的库依赖选项“-I dir”和“-L dir”。“-I dir”正如上表中所述,“-I dir”选项可以在头文件的搜索路径列表中添加 dir 目录。由于 Linux 中头文件都默认放到了“/usr/include/”目录下,因此,当用户希望添加放置在其他位置的头文件时,就可以通过“-I dir”选项来指定,这样
20、,gcc 就会到相应的位置查找对应的目录。比如在“/root/workplace/Gcc”下有两个文件:/*hello1.c*/#include int main()printf(Hello!n);return 0;/*my.h*/#include 这样,就可在 gcc 命令行中加入“-I”选项:嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org rootlocalhost Gcc gcc hello1.c I/root/workplace/Gcc/-o hello1 这样,gcc 就能够执行出正确结果。“-L dir”选项“
21、-L dir”的功能与“-I dir”类似,能够在库文件的搜索路径列表中添加 dir目录。例如有程序 hello_sq.c 需要用到目录“/root/workplace/Gcc/lib”下的一个动态库libsunq.so,则只需键入如下命令即可:rootlocalhost Gcc gcc hello_sq.c L/root/workplace/Gcc/lib lsunq o hello_sq 需要注意的是,“-I dir”和“-L dir”都只是指定了路径,而没有指定文件,因此不能在路径中包含文件名。另外值得详细解释一下的是“-l”选项,它指示 gcc 去连接库文件 libsunq.so。由于
22、在 Linux 下的库文件命名时有一个规定:必须以 l、i、b 3 个字母开头。因此在用-l选项指定链接的库文件名时可以省去 l、i、b 3 个字母。也就是说 gcc 在对“-lsunq”进行处理时,会自动去链接名为 libsunq.so 的文件。(2)告警和出错选项 gcc 的告警和出错选项如表 3.8 所示。表 3.5 gcc 总体选项列表 选 项 含 义-ansi 支持符合 ANSI标准的 C 程序-pedantic 允许发出 ANSI C 标准所列的全部警告信息 续表 选 项 含 义-pedantic-error 允许发出 ANSI C 标准所列的全部错误信息-w 关闭所有告警-Wal
23、l 允许发出 gcc 提供的所有有用的报警信息-werror 把所有的告警信息转化为错误信息,并在告警发生时终止编译过程 下面结合实例对这几个告警和出错选项进行简单的讲解。如有以下程序段:#include void main()long long tmp=1;printf(This is a bad code!n);嵌入式 Linux 操作系统第 3 章 嵌入式 Linux 编程环境 华清远见嵌入式学院:www.embedu.org return 0;这是一个很糟糕的程序,读者可以考虑一下有哪些问题?“-ansi”该选项强制 gcc 生成标准语法所要求的告警信息,尽管这还并不能保证所有没有警告
24、的程序都是符合 ANSI C 标准的。运行结果如下所示:rootlocalhost Gcc#gcc ansi warning.c o warning warning.c:在函数“main”中:warning.c:7 警告:在无返回值的函数中,“return”带返回值 warning.c:4 警告:“main”的返回类型不是“int”可以看出,该选项并没有发现“long long”这个无效数据类型的错误。“-pedantic”允许发出 ANSI C 标准所列的全部警告信息,同样也保证所有没有警告的程序都是符合 ANSI C 标准的。其运行结果如下所示:rootlocalhost Gcc#gcc
25、pedantic warning.c o warning warning.c:在函数“main”中:warning.c:5 警告:ISO C90 不支持“long long”warning.c:7 警告:在无返回值的函数中,“return”带返回值 warning.c:4 警告:“main”的返回类型不是“int”可以看出,使用该选项查看出了“long long”这个无效数据类型的错误。“-Wall”允许发出 gcc 能够提供的所有有用的报警信息。该选项的运行结果如下所示:rootlocalhost Gcc#gcc Wall warning.c o warning warning.c:4 警告
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式Linux操作系统 嵌入式Linux操作系统3 嵌入式Linux编程环境 嵌入式 Linux 操作系统 编程 环境
限制150内