原标题:【新视频进度】国庆节至今更新6节"嵌入式Linux应用开发基础"
说到做到,韦东山老师国庆没有休息,录了4节新视频,到目前快速入门-嵌入式Linux应用开发基础知识已更新6节:
01.HelloWorld背后没那么简单
02.GCC编译器的使用
03.Makefile规则与示例
04.通用Makefile的使用
05.通用Makefile的解析
06.文件IO
下载地址:
https://eyun.baidu.com/s/3dFZmEgp
密码:6FJk ,
路径:04_快速入门->01_嵌入式Linux应用开发基础知识
下面将简单介绍,并给出直接观看的3个视频(平台限制了视频个数,只能插入3个,其他的给链接)
01.HelloWorld背后没那么简单
1,交叉编译hello.c准备工作:
① 解压工具链、设置PATH环境变量,确定编译器名称;然后才可以编译。
② 要在板子上运行,使用NFS会比较方便。
这2点,都可以参考开发板的高级用户使用手册。
2 ,请回答这几个问题
① 怎么确定交叉编译器中头文件的默认路径?
进入交叉编译器的目录里,执行:find -name “stdio.h”,它位于一个“include”目录下的根目录里。
这个“include”目录,就是要找的路径。
② 怎么自己指定头文件目录?
编译时,加上“-I ”这样的选项。
③ 怎么确定交叉编译器中库文件的默认路径?
进入交叉编译器的目录里,执行:find -name lib,可以得到xxxx/lib、xxxx/usr/lib,一般来说这2个目录就是要找的路径。
如果有很多类似的lib,进去看看,有很多so文件的目录一般就是要找的路径。
④ 怎么自己指定库文件目录、指定要用的库文件?
编译时,加上“-L ”这样的选项,用来指定库目录;
编译时,加上“-labc”这样的选项,用来指定库文件libabc.so。
02.GCC编译器的使用
1, GCC编译过程(精简版)一个C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和链接(linking)等4步才能变成可执行文件。
在日常交流中通常使用“编译”统称这4个步骤,如果不是特指这4个步骤中的某一个,本教程也依惯例使用“编译”这个统称。
cc1 main.c -o /tmp/ccXCx1YG.s
as -o /tmp/ccZfdaDo.o /tmp/ccXCx1YG.s
cc1 sub.c -o /tmp/ccXCx1YG.s
as -o /tmp/ccn8Cjq6.o /tmp/ccXCx1YG.s
collect2 -o test /tmp/ccZfdaDo.o /tmp/ccn8Cjq6.o....
2,常用编译选项
在学习时,我们暂时只需要了解下表中的选项。
选项
描述
-E
预处理,开发过程中想快速确定某个宏可以使用“-E -dM”
-c
把预处理、编译、汇编都做了,但是不链接
-o
指定输出文件
-I
指定头文件目录
-L
指定链接时库文件目录
-l
指定链接哪一个库文件
3,怎么编译多个文件
① 一起编译、链接:
gcc -otest main.c sub.c
② 分开编译,统一链接:
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -o test main.o sub.o
4,制作、使用动态库制作、编译:
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o生成动态库)
gcc -o test main.o -lsub -L /libsub.so/所在目录/
运行:
① 先把libusb.so放到PC或板子上的/lib目录,然后就可以运行test程序。
② 如果不想把libusb.so放到/lib,也可以放在某个目录比如/a,然后如下执行:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
./test
5,制作、使用静态库
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
ar crs libsub.a sub.o sub2.o sub3.o(可以使用多个.o生成静态库)
gcc -o test main.o libsub.a (如果.a不在当前目录下,需要指定它的绝对或相对路径)
运行:
不需要把静态库libsub.a放到板子上。
6,很有用的选项
gcc -E main.c // 查看预处理结果,比如头文件是哪个
gcc -E -dM main.c > 1.txt // 把所有的宏展开,存在1.txt里
gcc -Wp,-MD,abc.dep -c -o main.o main.c // 生成依赖文件abc.dep,后面Makefile会用
03.Makefile规则与示例
腾讯视频链接:
https://v.qq.com/x/page/u30051mk8au.html (复制到浏览器中打开)
1, Makefile的使用
在Linux中使用make命令来编译程序,特别是大程序;而make命令所执行的动作依赖于Makefile文件。最简单的Makefile文件如下:
hello: hello.c
gcc -o hello hello.c
clean:
rm -f hello
将上述4行存为Makefile文件(注意必须以Tab键缩进第2、4行,不能以空格键缩进),放入01_hello目录下,然后直接执行make命令即可编译程序,执行“make clean”即可清除编译出来的结果。
make命令根据文件更新的时间戳来决定哪些文件需要重新编译,这使得可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。
要想完整地了解Makefile的规则,请参考《GNU Make 使用手册》,以下仅粗略介绍。
参考文档:gunmake.htm
① 为什么需要Makefile
怎么高效地编译程序?
想达到什么样的效果?请参考Visual Studio:修改源文件或头文件,只需要重新编译牵涉到的文件,就可以重新生成APP
② Makefile其实挺简单
一个简单的Makefile文件包含一系列的“规则”,其样式如下:
目标(target)…:依赖(prerequiries)…
命令(command)
如果“依赖文件”比“目标文件”更加新,那么执行“命令”来重新生成“目标文件”。
命令被执行的2个条件:依赖文件比目标文件新,或是 目标文件还没生成。
③ 先介绍Makefile的2个函数
A. $(foreachvar,list,text)
简单地说,就是for each var in list, change it to text。
对list中的每一个元素,取出来赋给var,然后把var改为text所描述的形式。
例子:
objs := a.o b.o
dep_files := $(foreach f, $(objs), .$(f).d) // 最终 dep_files := .a.o.d .b.o.d
B. $(wildcardpattern)
pattern所列出的文件是否存在,把存在的文件都列出来。
例子:
src_files := $( wildcard *.c) //最终 src_files中列出了当前目录下的所有.c文件
④ 一步一步完善Makefile
第1个Makefile,简单粗暴,效率低:
test : main.c sub.c sub.h
gcc-o test main.c sub.c
第2个Makefile,效率高,相似规则太多太啰嗦,不支持检测头文件:
test : main.o sub.o
gcc-o test main.o sub.o
main.o : main.c
gcc-c -o main.o main.c
sub.o : sub.c
gcc-c -o sub.o sub.c
clean:
rm*.o test -f
第3个Makefile,效率高,精炼,不支持检测头文件:
test : main.o sub.o
gcc-o test main.o sub.o
%.o : %.c
gcc-c -o $@ $<
clean:
rm*.o test -f
第4个Makefile,效率高,精炼,支持检测头文件(但是需要手工添加头文件规则):
test : main.o sub.o
gcc-o test main.o sub.o
%.o : %.c
gcc-c -o $@ $<
sub.o : sub.h
clean:
rm*.o test -f
第5个Makefile,效率高,精炼,支持自动检测头文件:
objs := main.o sub.o
test : $(objs)
gcc-o test $^
# 需要判断是否存在依赖文件
# .main.o.d .sub.o.d
dep_files := $(foreach f, $(objs), .$(f).d)
dep_files := $(wildcard $(dep_files))
# 把依赖文件包含进来
ifneq ($(dep_files),)
include$(dep_files)
endif
%.o : %.c
gcc-Wp,-MD,.$@.d -c -o $@ $<
clean:
rm*.o test -f
distclean:
rm $(dep_files) *.o test -f
04.通用Makefile的使用
腾讯视频链接:
https://v.qq.com/x/page/i3005fxx8rh.html (复制到浏览器中打开)
我参考Linux内核的Makefile编写了一个通用的Makefile,它可以用来编译应用程序:
① 支持多个目录、多层目录、多个文件;
② 支持给所有文件设置编译选项;
③ 支持给某个目录设置编译选项;
④ 支持给某个文件单独设置编译选项;
⑤ 简单、好用。
使用git下载本教程的文档后,下列目录中就有说明和示例:
01_all_series_quickstart04_快速入门(正式开始)
01_嵌入式Linux应用开发基础知识source05_general_Makefile
插播,好多人不知道如何使用GIT下载新视频文档,这里再提一下,
步骤一,
下载双击安装Git Bash :
https://gitforwindows.org/
步骤二,
打开Git Bash,敲入命令
git clonehttps://git.dev.tencent.com/weidongshan/01_all_series_quickstart.git
不出意外的话,文档就下载到了C:Users目录下
更详细的Git使用教程见:
http://wiki.100ask.org/BeginnerLearningRoute
05.通用Makefile的解析
腾讯视频链接:
https://v.qq.com/x/page/c3005zxf7p3.html(复制到浏览器中打开)
① 零星知识点A. make命令的使用:
执行make命令时,它会去当前目录下查找名为“Makefile”的文件,并根据它的指示去执行操作,生成第一个目标。
我们可以使用“-f”选项指定文件,不再使用名为“Makefile”的文件,比如:
make -f Makefile.build
我们可以使用“-C”选项指定目录,切换到其他目录里去,比如:
make -C a/ -f Makefile.build
我们可以指定目标,不再默认生成第一个目标:
make -C a/ -f Makefile.buildother_target
B. 即时变量、延时变量:
变量的定义语法形式如下:
A = xxx //延时变量
B ?= xxx // 延时变量,只有第一次定义时赋值才成功;如果曾定义过,此赋值无效
C := xxx // 立即变量
D += yyy // 如果D在前面是连时变量,那么现在它还是延时变量;
//如果D在前面是立即变量,那么现在它还是立即变量
在GNU make中对变量的赋值有两种方式:延时变量、立即变量。
上图中,变量A是延时变量,它的值在使用时才展开、才确定。比如:
A = $@
test:
@echo$A
上述Makefile中,变量A的值在执行时才确定,它等于test,是延时变量。
如果使用“A :=$@”,这是立即变量,这时$@为空,所以A的值就是空。
C. 变量的导出(export):
在编译程序时,我们会不断地使用“make -C dir”切换到其他目录,执行其他目录里的Makefile。如果想让某个变量的值在所有目录中都可见,要把它export出来。
比如“CC = $(CROSS_COMPILE)gcc”,这个CC变量表示编译器,在整个过程中都是一样的。定义它之后,要使用“export CC”把它导出来。
D. Makefile中可以使用shell命令:
比如:
TOPDIR := $(shell pwd)
这是个立即变量,TOPDIR等于shell命令pwd的结果。
E. 在Makefile中怎么放置第1个目标:
执行make命令时如果不指定目标,那么它默认是去生成第1个目标。
所以“第1个目标”,位置很重要。有时候不太方便把第1个目标完整地放在文件前面,这时可以在文件的前面直接放置目标,在后面再完善它的依赖与命令。比如:
First_target: // 这句话放在前面
.... // 其他代码,比如include其他文件得到后面的xxx变量
First_target : $(xxx) $(yyy) // 在文件的后面再来完善
command
F. 假想目标:
我们的Makefile中有这样的目标:
clean:
rm-f $(shell find -name "*.o")
rm-f $(TARGET)
如果当前目录下恰好有名为“clean”的文件,那么执行“make clean”时它就不会执行那些删除命令。
这时我们需要把“clean”这个目标,设置为“假想目标”,这样可以确保执行“make clean”时那些删除命令肯定可以得到执行。
使用下面的语句把“clean”设置为假想目标:
.PHONY : clean
G. 常用的函数:
i. $(foreachvar,list,text)
简单地说,就是for each var in list, change it to text。
对list中的每一个元素,取出来赋给var,然后把var改为text所描述的形式。
例子:
objs := a.o b.o
dep_files := $(foreach f, $(objs), .$(f).d) // 最终 dep_files := .a.o.d .b.o.d
ii. $(wildcardpattern)
pattern所列出的文件是否存在,把存在的文件都列出来。
例子:
src_files := $( wildcard *.c) //最终 src_files中列出了当前目录下的所有.c文件
iii. $(filterpattern...,text)
把text中符合pattern格式的内容,filter(过滤)出来、留下来。
例子:
obj-y := a.o b.o c/ d/
DIR := $(filter %/, $(obj-y)) //结果为:c/ d/
iv. $(filter-outpattern...,text)
把text中符合pattern格式的内容,filter-out(过滤)出来、扔掉。
例子:
obj-y := a.o b.o c/ d/
DIR := $(filter-out %/, $(obj-y)) //结果为:a.o b.o
vi. $(patsubst pattern,replacement,text)
寻找`text’中符合格式`pattern’的字,用`replacement’替换它们。`pattern’和`replacement’中可以使用通配符。
比如:
subdir-y := c/ d/
subdir-y:=$(patsubst %/, %, $(subdir-y)) // 结果为:c d
② 通用Makefile的设计思想A. 在Makefile文件中确定要编译的文件、目录,比如:
obj-y += main.o
obj-y += a/
“Makefile”文件总是被“Makefile.build”包含的。
B. 在Makefile.build中设置编译规则,有3条编译规则:
i. 怎么编译子目录?进入子目录编译:
$(subdir-y):
make-C $@ -f $(TOPDIR)/Makefile.build
ii. 怎么编译当前目录中的文件?
%.o : %.c
$(CC)$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -Wp,-MD,$(dep_file) -c -o $@ $<
iii. 当前目录下的.o和子目录下的built-in.o要打包起来:
built-in.o : $(cur_objs) $(subdir_objs)
$(LD)-r -o $@ $^
C. 顶层Makefile中把顶层目录的built-in.o链接成APP:
$(TARGET) : built-in.o
$(CC)$(LDFLAGS) -o $(TARGET) built-in.o
③ 情景演绎
06.文件IO
参考书:
这2本书的内容类似,第一本对知识点有更细致的描述,适合初学者;第二本比较直接,一上来就是各种函数的介绍,适合当作字典,不懂时就去翻看一下。
做纯Linux应用的人,看这2本书就可以了,不需要学习我们的视频。我们的侧重于“嵌入式Linux”。
在Linux系统中,一切都是“文件”:普通文件、驱动程序、网络通信等等。所有的操作,都是通过“文件IO”来操作的。所以,很有必要掌握文件操作的常用接口。
1, 文件从哪来?
2, 怎么访问文件?
① 通用的IO模型:open/read/write/lseek/close② 不是通用的函数:ioctl/mmap
3, 怎么知道这些函数的用法?
Linux下有3大帮助方法:help、man、info。
想查看某个命令的用法时,比如查看ls命令的用法,可以执行:
ls --help
help只能用于查看某个命令的用法,而man手册既可以查看命令的用法,还可以查看函数的详细介绍等等。它含有9大分类,如下:
1 Executable programs or shell commands // 命令
2 System calls (functions provided by the kernel) // 系统调用,比如 man 2 open
3 Librarycalls (functions within program libraries) // 函数库调用
4 Specialfiles (usually found in /dev) // 特殊文件, 比如 man 4 tty
5 Fileformats and conventions eg /etc/passwd // 文件格式和约定, 比如man 5 passwd
6 Games // 游戏
7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) //杂项
8 System administration commands (usually only for root)
// 系统管理命令
9 Kernel routines [Non standard] //内核例程
比如想查看open函数的用法时,可以直接执行“man open”,发现这不是想要内容时再执行“man 2 open”。
在man命令中可以及时按“h”查看帮助信息了解快捷键。常用的快捷键是:
f 往前翻一页
b 往后翻一页
/patten 往前搜
?patten 往后搜
就内容来说,info手册比man手册编写得要更全面,但man手册使用起来更容易些。
以书来形容info手册和man手册的话,info手册相当于一章,里面含有若干节,阅读时你需要掌握如果从这一节跳到下一节;而man手册只相当于一节,阅读起来当然更容易。
就个人而言,我很少使用info命令。
可以直接执行“info”命令后,输入“H”查看它的快捷键,在info手册中,某一节被称为“node”,常用的快捷键如下:
Up Move up one line.
Down Move down one line.
PgUp Scroll backward one screenful.
PgDn Scroll forward one screenful.
Home Go to the beginning of this node.
End Go to the end of this node.
TAB Skip to the next hypertext link.
RET Follow the hypertext link under the cursor.
l Go back to the last node seen in this window.
[ Go to the previous node in the document.
] Go to the next node in the document.
p Go to the previous node on this level.
n Go to the next node on this level.
u Go up one level.
t Go to the top node of this document.
d Go to the main 'directory' node.
4.4 系统调用函数怎么进入内核?
4.5 内核的sys_open、sys_read会做什么?
课程评价
最后,如果你对新视频有任何建议,都可以加群讨论。
加群方式:先加管理员微信:13266630429,验证:新视频。期待您的加入。返回搜狐,查看更多
责任编辑: