嵌入式Linux应用开发完全手册(一)嵌入式Linux基础知识
2017-08-12 21:34
204 查看
嵌入式Linux应用开发完全手册
3 嵌入式Linux基础知识
3.1 交叉编译工具
编译工具链,编译工作由几个步骤完成,分别用到了不同的工具PC端应用
gcc
ld
objcopy
objdump
交叉编译(编译和运行在不同的环境下),arm平台工具链
arm-linux-gcc
arm-linux-ld
3.1.1 arm-linux-gcc
C/C++文件的编译步骤预处理 preprocessing
编译 compilation
汇编 assembly
连接 linking
预处理
根据预处理命令(#开头的命令)修改源文件,形成.i文件
用到额工具是arm-linux-cpp
编译
将经过预处理的.i文件,翻译成汇编代码,.s文件
用到的工具是ccl
汇编
将汇编代码文件.s翻译成目标文件 .o文件
用到的工具是arm-linux-as
连接
将汇编生成的目标文件和库文件连接起来,最终生成特定平台的可执行文件
用到的工具是arm-linux-ld
连接器处理的文件一般包括
- .o 目标文件
- .a 库文件
arm-linux-gcc的重要选项
-E 预处理 :预处理结果通过stdout显示出来
-S 预处理、编译 :可以生成.s文件
-c 预处理、编译、汇编 :可以生成.o文件
-o 指定输出文件名 :如果不指定名成,按照一般规则生成
-v 显示制作gcc命令时的配置 :显示更详细的编译信息
-Wall 显示所有警告信息 :Warning ALL
-g 产生调试信息,以便GDB使用 : 要使用gdb调试,必须有这个选项
-O 优化选项 :O0,O1,O2,O3 4级优化,一般应用选O2
[object-file-name] :连接的时候,目标文件和库文件名称
-l[library] :连接名为l[library]的库文件,库文件名称规则lib[libraay].so
-nostartfiles :不连接系统标准启动文件,编译bootloader, 内核的时候会用到
-nostdlib :不连接系统标准启动文件和标准库文件,编译bootloader和内核会用到
-static :组织连接共享库,打开这个选线柜让编译出来的结果很大,不动态连接一些库,那么就都包含在编译结果里边了
-shared :生成库文件
-I[dir] :头文件搜索路径中添加 dir
-L[dir] :-l指定某个库需要连接的时候,这个参数增加搜索路径,比如-L. 当前目录作为搜索目录添加进来
/ * 举例 */ [main.c] - include [sub.h] [sub.h] [sub.c] - include [sub.h] -------- gcc -c -o main.o main.c gcc -c -o sub.o sub.c gcc -o test main.o sub.o -------- gcc -S -o main.s main.c gcc -E main.c | less -------- gcc -shared -o sub.a sub.o sub2.o sub3.o
arm-linux-ld选项
-T :指定代码段、数据段、bss段的起始位置,或者指定一个连接脚本
:-T参数只用于连接bootloader,内核等“没有底层软件支持”的软件
:连接运行于操作系统之上的软件时,不需要-T,使用默认连接即可
-Ttext startaddr -Tdata startaddr -Tbss startaddr /* 代码段运行地址0x00000000,没有定义数据段,bss段,它们依次放在代码段后面 */ arm-linux-ld -Ttext 0x00000000 -g ledon.o -o ledon_elf /* 使用连接脚本设置地址 */ arm-linux-ld -Ttimer.lds -o timer_elf head.o init.o interrupt.o main.o [timer.lds] -------- SECTIONs { . = 0x30000000; .text : {*(.text)} .rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : {*(.data)} .bss ALIGN(4) : {*(.bss) *(COMMON)} } --------
arm-linux-objcopy选项
arm-linux-objcopy用来赋值一个目标文件到另一个文件中,可以使用不同于源文件的格式来输出目的文件,也就是可以用来进行格式转换
可以用它来将elf文件转换位二进制可执行文件
/* 编译bootloader和内核的时候,用此命令将elf文件转换为二进制文件 */ arm-linux-objcopy -O binary -S elf_file bin_file
arm-linux-objdump选项
用于显示二进制文件信息,常用来查看反汇编代码
/* 将elf格式文件反汇编 */ arm-linux_objdump -D elffile > dis_file /* 将二进制文件反汇编 */ arm-linux-objdump -D binary -m arm bin_file > dis_file
3.2 Makefile
Makefile就是一个名字是Makefile的文件。内部缩进必须使用Tab,不能转换为空格。这里介绍Makefile的最基本的规则。
格式
[Makefile] -------- target : prerequiries <Tab>command --------
目标 通常是要生成的文件名称,可以是可执行文件或者obj文件。也可以是一个需要执行的动作名称,比如“clean”
依赖 用来产生目标的原料(比如源文件),一个目标通常有几个依赖。
命令 生成目标时进行的动作。可以有若干命令,一个命令一行
依赖发生改变,目标就需要通过命令重新生成。如果依赖没有改变,目标不需要重新生成。
/* 一个最简单的例子 */ hello: hello.c gcc -o hello hello.c clean: rm -f hello
变量及赋值
延时变量=
?=
立即变量
:=
扩展变量
+=
src := $(shel ls *.c) /* 立即变量的赋值 */ obj := $(patsubst %.c, %.o, $(src)) obj += temp.o /* 扩展变量 */ test: $(obj) /* 变量使用 */ gcc ...
Makefile函数
Makefile里边可以使用一些函数,格式如下$(function arguments)
字符串替换和分析函数
$(subst from, to, text)
$(patsubst pattern, replacement, text)
$(strip string)
$(findstring find, in)
$(filter pattern…, text)
$(filterout pattern…, text)
$(sort list)
$(subst ee, EE, feet on the street) fEEt on the strEEt $(patsubst %.c, %.o, x.c.c bar.c) x.c.o ar.o $(strip a b c a b c $(findstring a, a b c) a $(findstring a, b c) $(filter %.c %.s, foo.c bar.c baz.s ugh.h) foo.c bar.c baz.s $(filterout %.c %.s, foo.c bar.c baz.s ugh.h) ugh.h $(sort foo bar lose) bar foo lose
文件名函数
$(dir names)
$(notdir names)
$(suffix names)
$(basename names)
$(addsuffix suffix, names)
$(addprefix prefix, names)
$(wildcard pattern)
$(dir src/foo.c hacks) src/ ./ $(notdir src/foo.c hacks) foo.c hacks $(suffix src/foo.c src-1.0/bar.c hacks) .c .c $(basename src/foo.c src-1.0/bar.c hacks) src/foo src-1.0/bar hacks $(addsuffix .c, foo bar) foo.c bar.c $(addprefix src/, foo bar) src/foo, src/bar $(wildcard *.c) /* 等于 $(shell ls *.c)*/ 1.c 2.c
其他
$(foreach var, list, text)
$(if condition, then-part, else-part)
$(origin var)
$(shell cmd)
dirs := a b c d files := $(foreach dir, $(dir), $(wildcard $(dir)/*)) /* files 变量赋值为 a/ b/ c/ d/ 下边的所有文件*/
自动变量
$@ 规则的目标文件
$^ 所有依赖名字,名字之间空格分开
$< 第一个依赖的名字
一个稍微复杂点的例子
src := $(shell *.c) objs := $(patsbust %.c, %.o, $(src)) test: $(objs) gcc -o $@ $^ %.o: %.c gcc -c -o $@ $< clean: rm -f test *.o
3.3 常用ARM汇编指令和ATPCS规则
ARM汇编指令
相对跳转b, bl数据传送指令mov
地址读取伪指令ldr
内存访问指令 ldr str ldm stm
加减 add sub
程序转台寄存器访问指令 msr mrs
其他 .extern .text .global
ATPCS
ARM程序和Thumb程序中子程序调用规则。- 寄存器
- r0 - r3 传递参数
- r4 - r11 保存局部变量
- r12 子程序间scratch寄存器,别名ip
- r13 数据栈指针,别名sp
- r14 连接寄存器,别名lr
- r15 程序计数器,别名pc
- 堆栈
- FD 满减堆栈
- 8字节对齐
- stmdb ldmia 指令访问,db: Decending before, ia:increase after
- 参数传递规则
- 参数不超过4个,用r0 - r3,超过4个用堆栈
- 返回结果用r0 - r3
4 Windows,Linux环境下的工具、命令介绍
4.1 windows
Source insight
Cuteftp, SecureCRT, tftp
这几个工具用Xshell就全搞定了,不用书上介绍的这几个 *4.2 Linux
KScope
CKermit
Vi
这几个工具暂时用不到,就用windows环境 Samba连接Linux即可,Vi可以通过Vimtutor熟悉下 *grep find 命令
grepgrep [operation] PATTERN [FILE…]
grep "request_irq" * -R // *表示当前目录下所有文件,-R 表示递归查找所有子目录 grep "request_irq" kernel -R // 在当前目录的kernel目录下查找,包含所有子目录 find -name "*.[ch]" | xargs grep "request_irq" // 在当前目录下所有的.c .h 文件中查找关键字
find
find [-H] [-L] [-P] [path…] [expression]
find -name "*fb*" find drivers/net -name "*fb*"
man
man [section] name
需要注意的是[section] 部分,因为同一个关键字,可以出现在不同的地方,比如uname 可以是shell命令,也可以是系统格调用,单纯根据关键字是无法定位的。*
section的定义
1 命令,比如ls grep find
2 系统调用,比如open read socket
3 库调用,比如fopen, fread
4 特殊文件 比如 /dev 目录下的文件
5 文件格式和惯例,比如/etc/passwd
6 游戏
7 其他
8 系统管理命令,如mount
9 内核例程
man uname man 2 uname
tar
tar有打包、解包、压缩、解压缩 4种功能
压缩格式
gzip .gz .z
bzip2 .bz2
tar命令常用选项
c 创建
x 提取
z 使用gzip方式处理
j 使用bzip2方式处理
f 文件,接文件名
最常用的选项组合套路
czf, cjf 创建压缩包
xzf, xjf 解压缩
tar czf dirA.tar.gz dirA tar cjf dirA.tar.bz2 dirA tar xzf dirA.tar.gz tar xjf dirA.tar.bz2
diff patch
diff是UNIX标准的文件差异对比工具和格式
diff常用选项
-u 显示上下文中一些相同的行
-r 递归比较各目录下的文件
-N 不存在的文件当做空文件
-w 忽略空格
-B 忽略空行
用diff命令制作补丁文件
diff -urNwB linux-2.6.22.6 linux-2.6.22.6_ok > linux-2.6.22.6_ok.diff
patch的用法,patch用来把一个补丁文件(.diff)合并到工程中
cd linux-2.6.22.6 patch -p1 < ../linux-2.6.22.6_ok.diff
其中参数-p1 中是数字1,不是子母l。含义是忽略补丁文件中所有路径相关字段的的第一级目录,具体应该忽略几级,需要打开diff文件查看一下,跟patch执行的当前路径对比一下。
相关文章推荐
- 嵌入式Linux基础知识
- s3c2440硬件学习笔记----嵌入式Linux基础知识和开发环境的构建
- TQ2440 学习笔记—— 11、嵌入式编程基础知识【arm-linux-objcopy、objdump选项】
- 嵌入式linux基础知识大纲
- 【分享】4412开发板-嵌入式Linux开发需要掌握的基础知识和技能
- TQ2440 学习笔记—— 10、嵌入式编程基础知识【arm-linux-ld 选项】
- Linux系统基础知识-嵌入式迅为4412开发板学习笔记
- 嵌入式Linux基础知识1(嵌入式Linux开发流程)
- 嵌入式Linux串口应用编程基础知识
- 嵌入式Linux基础知识
- 嵌入式Linux基础知识3(嵌入式Linux开发入门的6个步骤 新手必看)
- 【嵌入式Linux+ARM】硬件相关基础知识(门电路_UART_I2C_SPI)
- 嵌入式Linux系统基础知识
- 嵌入式Linux基础知识2(嵌入式Linux开发环境搭建)
- 【分享】4412开发板-嵌入式Linux开发须要掌握的基础知识和技能
- 嵌入式Linux教程基础知识
- 嵌入式Linux系统基础知识(转)
- TQ2440 学习笔记—— 9、嵌入式编程基础知识【arm-linux-gcc 选项】
- 嵌入式Linux基础知识7(win7系统DOS命令行不能用)
- 【嵌入式Linux+ARM】硬件相关基础知识(门电路_UART_I2C_SPI)