嵌入式Linux驱动开发笔记(二)

嵌入式Linux驱动开发笔记(二)

二、Linux C 编程

1.设置VI编辑器TAB 键为 4 字节

VI 编辑器默认 TAB 键为 8 空格,我们改成 4 空格,用 vi 打开文件/etc/vim/vimrc

vi /etc/vim/vimrc

在此文件最后面输入如下代码:

set ts=4  

请添加图片描述
修改完成以后,在指令模式下输入:wq,保存并关闭文件。 提示:E45: 已设定选项 ‘readonly‘ (请加 ! 强制执行)

解决办法如下:

(不过这种方法有个要求就是当前编辑用户必须在 sudoers这个文件中,这也是执行sudo命令的要求)

// 保存文件时用
// tee 用于读取输入文件,同时保存,%表示当前编辑文件
w ! sudo tee %

2.VIM 编辑器显示行号

用 vi 打开文件/etc/vim/vimrc

vi /etc/vim/vimrc

在此文件最后面输入如下代码:

set nu

修改完成以后,保存并关闭文件。

3.编译代码

Ubuntu 下的 C 语言编译器是 GCC, GCC 编译器在我们 Ubuntu 的时候就已经默认安装好了,可以通过如下命令查看 GCC 编译器的版本号:

gcc -v  

GCC 编译器来编译 main.c 文件

gcc main.c

使用参数“-o”来指定编译生成的可执行文件名字

gcc main.c –o main  
4.GCC编译器

gcc 命令格式如下:

gcc [选项] [文件名字]
主要选项如下:
-c: 只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
-o: <输出文件名>用来指定编译结束以后的输出文件名,如果不使用这个选项的话 GCC 默
认编译出来的可执行文件名字为 a.out。
-g: 添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编
译的时候生成调试所需的符号信息。
-O: 对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进
行优化,这样产生的可执行文件执行效率就高。
-O2: 比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。
5.GCC编译流程

GCC 编译器的编译流程是:预处理、编译、汇编和链接。预处理就是展开所有的头文件、替换程序中的宏、解析条件编译并添加到文件中。编译是将经过预编译处理的代码编译成汇编代码,也就是我们常说的程序编译。汇编就是将汇编语言文件编译成二进制目标文件。链接就是将汇编出来的多个二进制目标文件链接在一起,形成最终的可执行文件,链接的时候还会涉及到静态库和动态库等问题。

6.Makefile 基础

解决大工程编译的工具: make,描述哪些文件需要编译、哪些需要重新编译的文件就叫做 Makefile,
Makefile 就跟脚本文件一样, Makefile 里面还可以执行系统命令。使用的时候只需要一个 make 命令即可完成整个工程的自动编译,极大的提高了软件开发的效率。

Makefile 文件注意要点:

(1)在工程目录下创建名为“Makefile”的文件,文件名一定要叫做“Makefile”!!!区分大小写。

(2)所有行首需要空出来的地方一定要使用“TAB”键!不要使用空格键!这是Makefile 的语法要求。

7.Makefile 语法
(1)Makefile 语法 规则

Makefile 里面是由一系列的规则组成的,这些规则格式如下:

目标…... : 依赖文件集合……
	命令 1
	命令 2
	……

比如下面这条规则:

main : main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o

这条规则的目标是 main, main.o、 input.o 和 calcu.o 是生成 main 的依赖文件,如果要更新目标 main,就必须先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新,“更新”就是执行一遍规则中的命令列表。
命令列表中的每条命令必须以 TAB 键开始,不能使用空格!

make 命令会为 Makefile 中的每个以 TAB 开始的命令创建一个 Shell 进程去执行

(2)Make 的执行过程

1、 make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
2、当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
3、当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比
目标文件晚)的话就会执行后面的命令来更新目标。

总结一下: Makefile 中规则用来描述在什么情况下使用什么命令来构建一个特定的文件,这个文件就是规则的“目标”,为了生成这个“目标”而作为材料的其它文件称为“目标”的依赖,规则的命令是用来创建或者更新目标的。
除了 Makefile 的“终极目标”所在的规则以外,其它规则的顺序在 Makefile 中是没有意义的,“终极目标”就是指在使用 make 命令的时候没有指定具体的目标时, make 默认的那个目标,它是 Makefile 文件中第一个规则的目标,如果 Makefile 中的第一个规则有多个目标,那么这些目标中的第一个目标就是 make 的“终极目标”。

(3)Makefile 变量
#Makefile 变量的使用
objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)

Makefile 中的变量都是字符串!类似 C 语言中的宏 ,Makefile 中注释开头要用符号“#” ,变量的引用方法是“$(变量名)” ,定义变量 objects 的时候使用“=”对其进行了赋值, Makefile变量的赋值符还有其它两个“:=”和“?=”

【1】赋值符"="使用

#示例代码 赋值符"="使用
name = kid
curname = $(name)
name = sudeki

print:
	@echo curname: $(curname)

1)Makefile 要输出一串字符的话使用“echo”,就和 C 语言中的“printf”一样

2)“echo”前面加了个“@”符号,因为 Make 在执行的过程中会自动输出命令执行过程,在命令前面加上“@”的话就不会输出命令执行过程

3)赋值符“=”的神奇之处!借助另外一个变量,可以将变量的真实值推到后面去定义。也就是变量的真实值取决于它所引用的变量的最后一次有效值。

【2】赋值符":="的使用

#示例代码 赋值符":="的使用
name = kid
curname := $(name)
name = sudeki

print:
	@echo curname: $(curname)

赋值符":=",不会使用后面定义的变量,只能使用前面已经定义好的,这就是“=”和“:=”两个的区别。

【3】赋值符“?=” 的使用

#如果变量 curname 前面没有被赋值,那么此变量就是“sudeki”,如果前面已经赋过值了,那么就使用前面赋的值。
curname ?= sudeki  

【4】变量追加“+=”

Makefile 中的变量是字符串,有时候我们需要给前面已经定义好的变量添加一些字符串进去,此时就要使用到符号“+=”,比如如下所示代码:

objects = main.o inpiut.o
objects += calcu.o
(4)Makefile 模式规则

模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似于通配符, a.%.c 就表示以 a.开头,以.c 结束的所有文件。当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方
法如下:

%.o : %.c
	命令
(5)Makefile 自动化变量

所谓自动化变量就是这种变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中,常用的自动化变量如表 :
请添加图片描述
7 个自动化变量中,常用的三种: $@、 $< 和 $^

(6)Makefile 伪目标

Makefile 有一种特殊的目标——伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。
使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突 。

(7)Makefile 条件判断

Makefile 支持条件判断,语法有两种如下:

<条件关键字>
	<条件为真时执行的语句>
endif

以及

<条件关键字>
	<条件为真时执行的语句>
else
    <条件为假时执行的语句>
endif

其中条件关键字有 4 个: ifeq、 ifneq、 ifdef 和 ifndef ,feq 用来判断是否相等, ifneq 就是判断是否不
相等,ifeq 用法如下:

ifeq(<参数1>,<参数2>)
ifeq'<参数1>,<参数2>'
ifeq"<参数1>","<参数2>"
ifeq"<参数1>",'<参数2>'
ifeq'<参数1',"<参数2>"

ifdef 和 ifndef 的用法如下:

ifdef <变量名>

如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。“变量名”同样可以是一个函数的返回值。 ifndef 用法类似,但是含义用户 ifdef 相反。

(7)Makefile 函数使用

Makefile 支持函数,类似 C 语言一样, Makefile 中的函数是已经定义好的,我们直接使用,不支持我们自定义函数。 函数的用法如下:

$(函数名 参数集合)
或者:
${
    
    函数名 参数集合}

调用函数和调用普通变量一样,使用符号“ ” 来 标 识 。 参 数 集 合 是 函 数 的 多 个 参 数 , 参 数 之 间 以 逗 号 “ , ” 隔 开 , 函 数 名 和 参 数 之 间 以 “ 空 格 ” 分 隔 开 , 函 数 的 调 用 以 “ ”来标识。参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“ ,”开头。

几个常用的函数:

【1】函数 subst

函数 subst 用来完成字符串替换,调用形式如下:

#此函数的功能是将字符串<text>中的<from>内容替换为<to>,函数返回被替换以后的字符串
$(subst <from>,<to>,<text>)

【2】函数 patsubst

函数 patsubst 用来完成模式字符串替换,使用方法如下:

$(patsubst <pattern>,<replacement>,<text>)  

此函数查找字符串 中的单词是否符合模式,如果匹配就用来替换掉,可以使用通配符“%”,表示任意长度的字符串,函数返回值就是替换后的字符串。如果中也包涵“%”,那么中的“%”将是中的那个“%”所代表的字符串, 例如:

$(patsubst %.c,%.o,a.c b.c c.c)  

意思是:将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o b.o c.o”。

【3】函数dir

函数 dir 用来获取目录,使用方法如下:

$(dir <names…>)  

此函数用来从文件名序列中提取出目录部分,返回值是文件名序列的目录
部分,比如:

$(dir </src/a.c>)

提取文件“/src/a.c”的目录部分,也就是“/src”。

提取文件“/src/a.c”的目录部分,也就是“/src”。

【4】函数 notdir

函数 notdir 看名字就是知道去除文件中的目录部分,也就是提取文件名,用法如下:

$(notdir <names…>)

此函数用与从文件名序列中提取出文件名非目录部分,比如:

$(notdir </src/a.c>)

提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。

提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。

【5】函数 foreach

foreach 函数用来完成循环,用法如下:

$(foreach <var>, <list>,<text>)

此函数的意思就是把参数中的单词逐一取出来放到参数中,然后再执行 所包含的表达式。每次 都会返回一个字符串,循环的过程中, 中所包含的每个字符串会以空格隔开,最后当整个循环结束时, 所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。

此函数的意思就是把参数中的单词逐一取出来放到参数中,然后再执行 所包含的表达式。每次 都会返回一个字符串,循环的过程中, 中所包含的每个字符串会以空格隔开,最后当整个循环结束时, 所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。

【6】函数 wildcard

通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard,使用方法如下:

$(wildcard PATTERN…)

比如:

$(wildcard *.c)

上面的代码是用来获取当前目录下所有的.c 文件,类似“%”。

猜你喜欢

转载自blog.csdn.net/WalterBrien/article/details/125111150