Linux程设复习提纲(二)
Chapter3-0
编译链接理解
常用的开发工具:GCC,GDB,二进制库,make
windows环境下的编译链接图
编译链接图
编译流程
- 预处理(头文件)
- 编译(转为汇编程序)
- 汇编(转为目标文件.o)
- 链接(引入C库)
在编译链接中头文件和#include分别是预处理和编译时处理
为什么要做链接(可能是因为要引入C库中的函数?我不清楚)
库和头文件
静态库和动态库的区别就在于链接这一个步骤中如何处理库
静态库
.a文件,gcc ar即可使用静态链接
在连接过程中将所有的函数库和.o文件进行连接,在编译(广义)时就已经完成了,程序在运行是与函数库没有关系,移植方便,但是因为函数库较多,所以浪费空间和资源,所有涉及到的代码会合并到一个可执行文件。
动态库
动态库的出现是因为静态库对于空间的浪费比较大,并且如果有软件厂商试图对静态库进行更新,需要更新整个静态库,非常耗费资源,需要全量更新。
动态库在程序编译(广义)是不会被链接到代码中,而是在运行的时候才会进行载入,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,节省了空间。实现了资源的共享
参考文章:博客园文章
其他语言的编译过程(非重点)
gcc命令参数
gcc用于编译C,gcc可以链接或者编译+链接
g++用于CPP
参数
- -E:只对源程序进行预处理
- -S:只对源程序进行预处理和编译
- -c:执行预处理、编译、汇编而不链接
- -o outputFile 指定输出文件名
- -g:产生调试工具必须的符号信息
- -O/On:在整个编译、链接过程中进行优化处理
- -Wall:显示所有的警告信息
- -Idir:指定额外的头文件搜索路径
- -Ldir:指定额外的库文件的搜索路径
- -lname:链接时搜索指定的库文件
- -DMACRO[=DEFN]:定义MACRO宏
文件类型
文件尾缀 | 文件类型 |
---|---|
.c | 一定会被预处理的C源码文件 |
.i | 不应该被预处理的C源码文件 |
.cc .cp .cpp .CPP .c++ .C .cxx | 一定会被预处理的CPP源码文件 |
.ii | 不应该被预处理的CPP源码文件 |
.h | C或者CPP的头文件 |
.H .hh | CPP的头文件 |
.s | 汇编码 |
.S | 必须被预处理的汇编码 |
.o | object file不会翻译 |
.a | 静态库文件 |
.so | 动态库文件 |
GDB(不要求,做了解)
Makefile读和写(要了亲命,我怎么知道什么是简单的读和写)
make & makefile
makefile描述模块间的依赖关系
make命令根据makefile对程序进行管理和维护,make判断被维护文件的时序关系
我裂开了,这一块实在是没法整,参考pdf,Ch3-0从第25页开始(痛苦面具),一下makefile内容均是本人的理解。
make命令
有了make命令就可以实现整个工程完全自动编译,make是一个命令工具。
make的命令格式:make [-f Makefile] [option] [target]
如:make target;make;make clean
make命令的Targets
通常是一个被生成的文件的名字,如可执行文件或者.o文件
target也可以是一个动作,如make clean中的clean(伪目标)
Makefile的规则
1 | target...:prerequisites ... |
- target是一个目标文件,可以是.o文件,也可以是执行文件
- prerequisites是要生成target所需要的文件或是目标
- command是make需要执行的命令(可以是任意的shell命令)
如:
1 | hello : main.o kbd.o |
Makefile执行的次序
- make会在当前目录下找到名字叫Makefile或makefile的文件
- 查找文件中的第一个目标文件(target),举例中的hello
- 如果hello文件不存在或是hello所依赖的文件修改时间要比hello新,就会执行后面所定义的命令来生成hello文件
- 如果hello所依赖的.o文件不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件(类似一个堆栈的过程)
- make根据.o文件的规则生成.o文件,然后再用.o文件生成hello文件
伪目标
如hello示例中的clean动作中的命令
- 伪目标不是一个文件,只是一个标签,所以make无法解析他的依赖关系和决定是否要执行。所以要执行一定要make clean
- 伪目标的取名不能和文件名重名
- 为了避免和文件重名的情况,可以使用标记”.PHONY”来指明一个目标是伪目标
- 伪目标一般没有依赖的文件,但可以有
- 伪目标同样可以放在第一个作为默认目标
多目标
当多个目标同时依赖于一个文件,并且其生成的命令大体类似,可以使用一个自动化变量“$@”表示着目前规则中所有的目标的集合
1 | bigoutput littleoutput : text.g |
等价于
1 | bigoutput : text.g |
一个例子(我看不太懂)
1 | TOPDIR = ../ |
预定义变量
- $< 第一个依赖文件的名称
- $? 所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚
- $+所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
- $^ 所有的依赖文件,以空格分开,不包含重复的依赖文件
- $* 不包括扩展名的目标文件名称
- $@ 目标的完整名称
- $% 如果目标是归档成员,则该变量表示目标的归档成员名称
多目标扩展
语法
1
2
3<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
...举例
1
2
3
4objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@- 目标从$object中获取
- “%.o”表明要所有以“.o”结尾的目标,即“foo.o bar.o”,就是变量$object集合的模式
- 依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是依赖的目标就是“foo.c bar.c”
上述代码等价于
1
2
3
4foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
makefile中的函数(仅需掌握,不需要会使用)
Chapeter3-1
七种文件类型
- 普通文件
- 文本和数据,没有特别的内部结构
- 字符设备文件
- 穿行端口的接口设备,例如键盘、鼠标
- 块设备文件
- 存储数据以供系统存取的接口设备,如键盘
套接字文件
- 用在网络数据连接
管道文件
- 解决多个程序同时存取一个文件造成的错误
- 链接文件
- 类似快捷方式
VFS主要原理,四种结构类型
VFS虚拟文件系统,是一个对各个文件系统提供统一的操作界面和编程接口的一个系统 ,可以直接使用read(),write(),open()函数而不需要关注底层的实现
VFS只存在在内存中,有四种结构类型
- 超级块对象(super block)
- 索引节点对象(i-node object)
- 目录项对象(dentry object)
- 文件对象(file object)
文件链接
硬链接
- 不同的文件名对应同一个inode
- 不能跨越文件系统
- 对应系统调用link
软连接(符号链接)
- 存储被链接文件的文件名(而不是inode)实现链接
- 可跨越系统调用
- 对应系统调用symlink