Chapter3-0

编译链接理解

常用的开发工具:GCC,GDB,二进制库,make

  • windows环境下的编译链接图

    windows编译链接

  • 编译链接图

    编译链接

    编译链接

    编译链接

编译流程

  1. 预处理(头文件)
  2. 编译(转为汇编程序)
  3. 汇编(转为目标文件.o)
  4. 链接(引入C库)

在编译链接中头文件和#include分别是预处理和编译时处理

为什么要做链接(可能是因为要引入C库中的函数?我不清楚)

库和头文件

静态库和动态库的区别就在于链接这一个步骤中如何处理库

静态库

.a文件,gcc ar即可使用静态链接

在连接过程中将所有的函数库和.o文件进行连接,在编译(广义)时就已经完成了,程序在运行是与函数库没有关系,移植方便,但是因为函数库较多,所以浪费空间和资源,所有涉及到的代码会合并到一个可执行文件。

动态库

动态库的出现是因为静态库对于空间的浪费比较大,并且如果有软件厂商试图对静态库进行更新,需要更新整个静态库,非常耗费资源,需要全量更新

动态库在程序编译(广义)是不会被链接到代码中,而是在运行的时候才会进行载入,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,节省了空间。实现了资源的共享

参考文章:博客园文章

其他语言的编译过程(非重点)

编译过程

delphi编译

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源码文件
.hC或者CPP的头文件
.H .hhCPP的头文件
.s汇编码
.S必须被预处理的汇编码
.oobject file不会翻译
.a静态库文件
.so动态库文件

GDB(不要求,做了解)

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的规则

target...:prerequisites ...

command

...

...
  • target是一个目标文件,可以是.o文件,也可以是执行文件
  • prerequisites是要生成target所需要的文件或是目标
  • command是make需要执行的命令(可以是任意的shell命令)

如:

hello : main.o kbd.o
gcc -o hello main.o kbd.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
clean :
rm edit main.o kbd.o

Makefile执行的次序

  1. make会在当前目录下找到名字叫Makefile或makefile的文件
  2. 查找文件中的第一个目标文件(target),举例中的hello
  3. 如果hello文件不存在或是hello所依赖的文件修改时间要比hello新,就会执行后面所定义的命令来生成hello文件
  4. 如果hello所依赖的.o文件不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件(类似一个堆栈的过程)
  5. make根据.o文件的规则生成.o文件,然后再用.o文件生成hello文件

伪目标

如hello示例中的clean动作中的命令

  • 伪目标不是一个文件,只是一个标签,所以make无法解析他的依赖关系和决定是否要执行。所以要执行一定要make clean
  • 伪目标的取名不能和文件名重名
  • 为了避免和文件重名的情况,可以使用标记”.PHONY”来指明一个目标是伪目标
  • 伪目标一般没有依赖的文件,但可以有
  • 伪目标同样可以放在第一个作为默认目标

多目标

当多个目标同时依赖于一个文件,并且其生成的命令大体类似,可以使用一个自动化变量“$@”表示着目前规则中所有的目标的集合

bigoutput littleoutput : text.g
generate text.g -$(subst output,,$@) > $@

等价于

bigoutput : text.g
generate text.g -big > bigoutput
littleoutput : text.g
generate text.g -little > littleoutput

一个例子(我看不太懂)

TOPDIR = ../
include $(TOPDIR)Rules.mak
EXTRA_LIBS +=
EXEC = $(INSTALL_DIR)/hello
OBJS = hello.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(EXTRA_LIBS)
install:
$(EXP_INSTALL) $(EXEC) $(INSTALL_DIR)

clean:
-rm -f $(EXEC) *.elf *.gdb *.o

预定义变量

  • $< 第一个依赖文件的名称
  • $? 所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚
  • $+所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
  • $^ 所有的依赖文件,以空格分开,不包含重复的依赖文件
  • $* 不包括扩展名的目标文件名称
  • $@ 目标的完整名称
  • $% 如果目标是归档成员,则该变量表示目标的归档成员名称

多目标扩展

  • 语法

    <targets ...>: <target-pattern>: <prereq-patterns ...>
    <commands>
    ...
  • 举例

    objects = 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”

    上述代码等价于

    foo.o : foo.c
    $(CC) -c $(CFLAGS) foo.c -o foo.o
    bar.o : bar.c
    $(CC) -c $(CFLAGS) bar.c -o bar.o

makefile中的函数(仅需掌握,不需要会使用)

makefile的函数

Chapeter3-1

七种文件类型

  • 普通文件
    • 文本和数据,没有特别的内部结构
  • 字符设备文件
    • 穿行端口的接口设备,例如键盘、鼠标
  • 块设备文件
    • 存储数据以供系统存取的接口设备,如键盘
  • 套接字文件

    • 用在网络数据连接
  • 管道文件

    • 解决多个程序同时存取一个文件造成的错误
  • 链接文件
    • 类似快捷方式

VFS主要原理,四种结构类型

VFS虚拟文件系统,是一个对各个文件系统提供统一的操作界面和编程接口的一个系统 ,可以直接使用read(),write(),open()函数而不需要关注底层的实现

VFS

VFS只存在在内存中,有四种结构类型

  • 超级块对象(super block)
  • 索引节点对象(i-node object)
  • 目录项对象(dentry object)
  • 文件对象(file object)

VFS四种结构类型

文件链接

硬链接

  • 不同的文件名对应同一个inode
  • 不能跨越文件系统
  • 对应系统调用link

软连接(符号链接)

  • 存储被链接文件的文件名(而不是inode)实现链接
  • 可跨越系统调用
  • 对应系统调用symlink
Linux程设复习提纲(三)