三、Ubuntu的文件系统
1、文件系统结构
(1)Linux中,最高层的目录称为根目录,表示为"/",其它所有目录都是由根目录衍生出来的。

(2)根目录下一层的目录结构:
|--------|----------------------------------------------------------------|
| 目录 | 内容 |
| /bin | 存放二进制可执行文件(或者说基础可执行命令,如ls、cp),这些命令在单用户模式下也能够使用,可以被root和一般的账号使用 |
| /boot | 存放Ubuntu内核和启动文件,比如vmlinuz-xxx,一般供root使用 |
| /cdrom | 早期用于挂载光盘镜像,现在Ubuntu中较少使用 |
| /dev | 存放设备驱动文件(或者说,内核会把设备抽象成文件,存放于此) |
| /etc | 存放系统配置文件,比如用户账号和密码文件,以及各种服务的起始地址 |
| /home | 系统默认的用户主文件夹,一般创建用户账户的时候,默认的用户主文件夹都会放到此目录下 |
| /lib | 存放系统启动和基础命令所需的共享库 |
| /lib64 | 存放64位共享库文件 |
| /media | 存放可插拔设备,比如SD卡和U盘,接入后都是挂载到这个目录中 |
| /mnt | 用户可使用的挂载点,如果用户要挂载一些额外的设备,可以挂载到此处 |
| /opt | 用户可选择在此存放第三方软件 |
| /proc | 虚拟文件系统,存放系统的运行文件和运行信息,其中的内容都存储在内存中,而非Flash |
| /root | root用户目录,也就是系统管理员目录 |
| /run | 存放系统运行时的临时文件、PID文件、Socket文件,重启后可能清空 |
| /sbin | 和/bin类似,也是存放二进制可执行文件,一般是系统开机过程中需要的命令 |
| /snap | Ubuntu的Snap包通常安装在这里 |
| /srv | 服务相关目录,比如网络服务 |
| /sys | 虚拟文件系统,记录内核信息和设备信息 |
| /tmp | 临时文件目录,通常重启后可能其中的内容会被清理 |
| /usr | 存放大部分应用程序、库、文档和共享资源 |
| /var | 存放经常变化的数据,如日志 |
2、绝对路径与相对路径
(1)绝对路径指的是从根目录"/"算起的路径,必须是以"/"开头。
cd /home/zevalin
cd /home/zevalin/桌面
cd /home/zevalin/桌面/test
(2)相对路径指的是从当前所在目录(pwd显示的目录)算起的路径,不以"/"开头。
①"."代表当前目录,"./"代表当前目录下。
②".."代表上一层目录,"../"代表上一级目录下。
当前在 /home/zevalin
ls ./test.txt # 当前目录下test.txt
ls ../abc.txt # 上一级目录下的abc.txt
ls Documents/ # 当前目录下Documents文件夹(省略"./"也可以)
四、Ubuntu的磁盘管理
1、磁盘文件
(1)"/dev/sd*"("*"是通配符)属于磁盘设备文件,位于"/dev"目录,代表磁盘硬件。不能直接读写磁盘内的文件,必须将磁盘分区挂载到指定目录(挂载点),通过访问挂载目录,才能读写磁盘中的数据。
(2)磁盘设备接入示例:
①准备文件系统为FAT32格式的U盘,将其接入虚拟机(接入方法参考上一章)。

②接入U盘后,"/dev"目录下会有对应该USB设备的文件"sd*",如果不确定哪些文件对应刚刚插入的U盘,可以插拔U盘,对比插拔过程中哪些文件有变化,那些文件夹就是U盘对应的文件夹(命名不一定唯一)。
bash
zevalin@zevalin-VMware-Virtual-Platform:/$ cd dev
zevalin@zevalin-VMware-Virtual-Platform:/dev$ ls sd*
sda sda1 sda2 sdb sdb1
③在本例中,sdb和sdb1是对应刚接入的U盘,其中/dev/sdb表示U盘本身,/dev/sdb1表示U盘的第1个分区。
2、磁盘和目录的容量查询命令
(1)df命令可用于查看整块分区总容量、已用、剩余空间、使用率,其语法与参数如下所示,虽然有文件/目录这个可选参数,但并不是说查看该文件或目录的大小,df会查这个路径所属的分区,再返回该分区的信息,如果不加这个参数,则查看所有挂载的分区信息。
df 选项 文件/目录 # 方括号表示可选参数,选项用"-"引出
|-----------|-----------------------------|
| 选项 | 作用 |
| -h | 以人性化单位展示大小数据 |
| -i | 查看inode使用情况 |
| -T | 额外显示文件系统类型 |
| -a | 列出所有文件系统(包含proc、sys等虚拟文件系统) |
| -t <类型> | 只展示指定类型文件系统 |
(2)du命令可递归遍历目录里的文件,统计文件或目录实际占用磁盘块大小,通常用来定位哪个文件夹占用空间大,其语法与参数如下所示,如果不加文件/目录这个参数,则默认为当前所在目录。
du 选项 文件/目录 # 方括号表示可选参数,选项用"-"引出
|------|----------------------------------|
| 选项 | 作用 |
| -h | 以人性化单位展示大小数据 |
| -s | 只输出总大小,不逐层打印子目录 |
| -a | 不仅统计目录,同时列出所有文件大小(默认只打印目录) |
| -d N | 限制递归层数,N为待定系数,比如"-d 1"表示只展示一级子目录 |
| -c | 最后额外输出总大小 |
| -x | 不进入其它挂载点(避免统计到别的分区) |
(3)示例:
bash
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ df -h
文件系统 大小 已用 可用 已用% 挂载点
tmpfs 1.5G 2.6M 1.5G 1% /run
/dev/sda2 49G 13G 34G 27% /
tmpfs 3.7G 0 3.7G 0% /dev/shm
none 1.0M 0 1.0M 0% /run/credentials/systemd-journald.service
none 1.0M 0 1.0M 0% /run/credentials/systemd-resolved.service
tmpfs 3.7G 8.0K 3.7G 1% /tmp
tmpfs 738M 88K 738M 1% /run/user/1000
/dev/sdb1 30G 64K 30G 1% /run/media/zevalin/6B0D-C39D
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ du -h
12K ./testdir
24K .
3、磁盘挂载与卸载
(1)前面提到过,如果将一个U盘接入Ubuntu,不能直接读写磁盘内的文件,必须将磁盘分区挂载到指定目录(挂载点,必须是已经存在的空目录),通过访问挂载目录,才能读写磁盘中的数据。
(2)mount是挂载命令,其语法与参数如下所示(其中设备名是"/dev/sd*"),如果不加任何可选参数,则可查看当前所有挂载信息。
mount 选项 -t \<文件系统类型\> -o 挂载参数 设备 挂载点 # 方括号表示可选参数,选项用"-"引出
|------------|------------------------------------------------------|
| 选项和挂载参数 | 作用 |
| -t | 指定文件系统类型(ext4、vfat、ntfs、iso9660等,现代Linux大多可自动识别,可省略) |
| -o | 附加挂载选项,多个用逗号隔开 |
| -a | 根据/etc/fstab文件,挂载所有允许自动挂载的分区 |
| -o ro | 只读挂载 |
| -o rw | 读写挂载(默认配置) |
| -o remount | 重新挂载(常用于修改读写权限,不用卸载) |
(3)umount是卸载命令,其语法与参数如下所示。
umount 选项 -t \<文件系统类型\> 设备/挂载点 # 方括号表示可选参数,选项用"-"引出
|------------|---------------------------------|
| 选项 | 作用 |
| -a | 卸载fstab里所有可卸载文件系统(系统核心分区不会被卸载) |
| -l | 延迟卸载(懒卸载,立刻脱离目录树,等进程不占用后再在后台清理) |
| -f | 强制卸载 |
| -t | 只卸载指定类型的文件系统 |
| -o remount | 重新挂载(常用于修改读写权限,不用卸载) |
(4)示例:
bash
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ tree
.
├── test.c
├── testdir
│ ├── test1.c
│ └── test2.c
└── USB
3 directories, 3 files
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ sudo mount /dev/sdb1 /home/zevalin/桌面/USB
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ tree
.
├── test.c
├── testdir
│ ├── test1.c
│ └── test2.c
└── USB
├── System Volume Information
│ ├── IndexerVolumeGuid
│ └── WPSettings.dat
└── usb_test.c
4 directories, 6 files
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ sudo umount /dev/sdb1
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ tree
.
├── test.c
├── testdir
│ ├── test1.c
│ └── test2.c
└── USB
3 directories, 3 files
4、磁盘分区和格式化
(1)将一个U盘接入Ubuntu,它默认是被划分为一整个分区的,比如sdb和sdb1两个文件是对应刚接入的U盘,那么/dev/sdb表示U盘本身,/dev/sdb1表示U盘被划分的第1个分区,如果继续对该U盘划分多个分区,那将会出现/dev/sdb2表示U盘被划分的第2个分区,以此类推。
(2)fdisk是交互式磁盘分区工具,用于查看、修改磁盘分区表(修改分区配置时磁盘设备不能挂载),由于是操作磁盘分区,它也需要root权限,其语法和参数定义如下。
fdisk 选项 磁盘设备 # 方括号表示可选参数,选项用"-"引出;不加磁盘设备时,搭配选项-l可查看全部磁盘分区
|------------|------------------------------------------------------|
| 选项 | 作用 |
| -l | 列出磁盘的分区表信息,不进入交互界面 |
| -t | 仅识别指定类型的分区表 |
| 交互指令(单个字母) | 作用 |
| m | 打印帮助信息 |
| p | 打印当前磁盘分区表 |
| n | 新建分区(会进入配置新建分区类型、分区编号、起始扇区、结束扇区的交互命令行,具体可参考交互命令行的提示) |
| d | 删除分区 |
| t | 修改分区类型ID |
| w | 保存分区表,写入磁盘,然后退出(修改生效) |
| q | 退出交互界面(修改不生效,也不保存) |
(3)磁盘分区完成后,需要对其进行格式化,也就是给每个分区都装一个文件系统(其中分区设备名是"/dev/sd*N",N为分区编号),可使用mkfs命令完成格式化,由于是操作磁盘分区,它也需要root权限,其法和参数定义如下。(格式化时,务必保证U盘中没有重要文件)
mkfs 选项 -t \<文件系统类型\> 分区设备 # 方括号表示可选参数,选项用"-"引出
|----|------------------------------------|
| 选项 | 作用 |
| -t | 指定文件系统类型(如ext4、vfat、ntfs、iso9660等) |
| -c | 格式化前检测坏块 |
| -v | 打印执行详情 |
| -L | 设置分区标签(别名) |
(4)完成磁盘分区和格式化操作后,将U盘弹出,然后再把U盘接入Windows系统开发电脑,会发现它已经被划分为多个盘。

五、Ubuntu的用户与用户组
1、用户
(1)Linux是一个多用户操作系统,不同的用户拥有不同的权限,可以查看和操作不同的文件。
(2)每个用户都有唯一的标识ID------UID。Linux将用户信息记录在/etc/passwd中,将用户密码(加密后)记录在/etc/shadow中。
(3)Ubuntu有三类用户:
①安装系统时初次创建的用户(UID默认为1000),默认加入sudo组,可sudo提权管理系统。
②root超级用户(UID为0),拥有最高权限。
③后续手动创建的普通交互用户(UID≥1001),默认没有sudo权限。
2、用户组
(1)为了方便对不同的用户做权限管理,Linux引入用户组的概念,可以设置非本组人员不能访问某些文件。
(2)每个用户可以同时属于多个组,每个用户组也都有唯一的标识------GID。Linux将用户组信息记录在/etc/group中。
3、图形化界面创建用户和用户组
(1)要使用图形化界面创建用户和用户组,需要安装gnome-system-tools工具,可直接在终端运行命令"sudo apt-get install gnome-system-tools",完成安装后,在应用中可直接找到"用户和组"这个软件。

(2)图形化交互界面如下图所示,整体操作比较简单,此处不做过多演示。

4、命令行创建用户和用户组
|-----------------------|------------------------------------------------------------|
| 命令 | 说明 |
| adduser <用户名> | 添加用户,自动创建家目录 |
| finger <用户名> | 查看用户信息,如登录名、家目录、shell、登录时间 |
| passwd <用户名> | 修改用户密码(root可以改所有人密码) |
| deluser <用户名> | 删除用户,默认不删除家目录,删除家目录需带参数,格式为"deluser --remove-home <用户名>" |
| addgroup <用户组名> | 添加用户组 |
| groups <用户名> | 查看用户属于哪些用户组 |
| delgroup <用户组名> | 删除用户组(用户组若不为空,默认不可删除) |
| getent group <用户组名> | 查看用户组中有哪些用户 |
六、Ubuntu的文件权限管理
1、文件权限概念
(1)文件权限是指不同的用户或用户组对某个文件拥有的权限,分为三种------读(r)、写(w)和可执行(x)。
(2)在使用ls命令的-l参数查看文件权限时,会显示一串10字符长度的字符串,如下所示,对于"-rw-rw-r--",从左往右依次拆解,"-"表示普通文件,后面9位每三位为一组,"rw-"表示文件拥有者权限,"rw-"表示文件拥有者所在组权限,"r--"表示其他用户权限。在10字符长度的字符串之后,ls将依次打印出该文件的硬链接数、所属用户、所属用户组、文件大小、修改时间和文件名。
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ ls -l test.c
-rw-rw-r-- 1 zevalin zevalin 86 Oct 18 22:10 test.c
(3)不同文件类型的表示:
|----|---------|
| 字符 | 含义 |
| - | 普通文件 |
| d | 目录文件夹 |
| l | 软链接 |
| b | 块设备(磁盘) |
| c | 字符设备 |
(4)针对可执行权限"x",目录的x权限和文件的x权限有区别,区别如下:
①目录的x权限:有目录x权限的用户才能通过cd命令访问其中的内容,否则如果只有r权限,用户就只能看到文件名,无法进去访问。
②文件的x权限:有文件x权限的用户才能运行这个文件(通常是程序或脚本)。
(5)三种权限可以用数字替代,r=4、w=2、x=1,不同权限组合有唯一对应的和。
|------|---------|
| 权限组合 | 代数和 |
| rwx | 4+2+1=7 |
| rw- | 4+2+0=6 |
| r-x | 4+0+1=5 |
| r-- | 4+0+0=4 |
| -wx | 0+2+1=3 |
| -w- | 0+2+0=2 |
| --x | 0+0+1=1 |
| --- | 0+0+0=0 |
2、文件权限修改
(1)可使用chmod命令修改文件或目录的权限:
①代数权限语法:
chmod <文件属主权限代数><文件属组权限代数><其他用户权限代数> <文件名/目录>
举例:chmod 777 test.sh 给文件属主、文件属组和其他用户开放所有权限
②符号权限语法:
chmod u/g/o/a+/-/=r/w/x <文件名/目录> # 加号表示增加权限,减号表示减少权限,等号表示修改权限为
举例1:chmod u+x test.sh # 给属主增加执行权限(u表示属主)
举例2:chmod g-w a.c # 取消同组用户的写权限(g表示属组)
举例3:chmod o+r test.txt # 给其他用户增加读权限(o表示其他用户)
举例4:chmod a+r test.txt # 所有人增加读权限(a表示全部)
③如果要修改目录中所有文件的权限,需要在"chmod"之后添加可选参数"-R",表示递归修改目录里所有文件的权限。
(2)可使用chown命令修改文件的所属用户(属主)和所属用户组(属组):
①修改文件所属用户:
chown <用户名> <文件名>
举例:sudo chown zevalin test.c # test.c文件的所属用户修改为zevalin
②同时修改文件所属用户和用户组:
chown <用户名>:<用户组名> <文件名>
举例:sudo chown zevalin:zevalin test.c # test.c文件的所属用户修改为zevalin,所属用户组修改为zevalin
③如果要修改目录中所有文件的归属,需要在"chown"之后添加可选参数"-R",表示递归修改目录里所有文件的归属。
七、Linux链接文件
1、链接文件的概念
(1)indoe是文件在磁盘上的编号,用来存放文件的元信息(属性),不存文件名、不存文件内容。在查找文件时,需要先找到indoe,才能读出文件的内容。
(2)Linux中有两种链接文件------符号链接(软链接)和硬链接。
①软链接的本质是存放源文件路径的快捷方式,类似于Windows中的快捷方式,指向独立的indoe,是一个独立的文件。
②硬链接的本质是同一个文件多个别名,多个文件名指向同一个indoe,相当于给同一个文件实体增加多个访问入口,不产生新文件。
2、链接创建
在Linux中,可使用ln命令创建链接文件,其语法如下:
ln 选项 <源文件/目录> <目标文件> # 方括号表示可选参数,选项用"-"引出
|----|-----------------------------|
| 选项 | 作用 |
| -s | 添加此参数代表创建符号链接,否则创建硬链接 |
| -f | 如果目标文件已经存在同名文件,强制将其删除,再创建链接 |
3、硬链接
(1)硬链接的特点:
①具有相同inode的多个文件互为硬链接文件,创建硬链接相当于给文件实体多了入口。
②只有把源文件和全部硬链接都删除,文件实体才会真正删除(利用此特点,可以防止文件被误删除)。
③修改源文件或者任意一个硬链接,其余文件的数据都会跟着改变。
④硬链接不能跨分区(跨文件系统),因为不同分区inode是独立编号体系,没法共用inode。
⑤硬链接不能链接目录,这是为了防止目录循环引用、目录树混乱。
(2)基于以上特点,在实际开发中,硬链接使用的频率并不高。
(3)示例:
bash
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ ln test.c hard_link
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ ls -li # 参数i表示在首列打印inode号
total 12
397976 -rw-rw-r-- 2 zevalin zevalin 86 Oct 18 22:10 hard_link
397976 -rw-rw-r-- 2 zevalin zevalin 86 Oct 18 22:10 test.c
398665 drwxrwxr-x 2 zevalin zevalin 4096 Oct 21 00:06 testdir
4、软链接
(1)软链接的特点:
①软链接可以链接到目录。
②软链接只保存路径字符串,不受inode分区隔离限制,可以跨文件系统(跨分区)。
③软链接存的只是源文件名/路径,如果把源文件删掉,路径将指向不存在,变成无效链接(使用命令ls查看时,无效链接会标红色)。
④使用命令ls的-l参数查看软链接时,会有"->"标记说明软链接指向的源文件。
(2)基于以上特点,在实际开发中,软链接使用的频率会比较高。
(3)使用ln命令创建软链接时,源文件/目录尽量使用绝对路径,当然,这并不是说相对路径禁止使用,如果使用相对路径,那它是相对于软链接所在位置的路径。
(4)示例:
bash
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ ln -s test.c symbol_link
zevalin@zevalin-VMware-Virtual-Platform:~/桌面$ ls -li # 参数i表示在首列打印inode号
total 8
402136 lrwxrwxrwx 1 zevalin zevalin 6 Oct 23 00:04 symbol_link -> test.c
397976 -rw-rw-r-- 1 zevalin zevalin 86 Oct 18 22:10 test.c
398665 drwxrwxr-x 2 zevalin zevalin 4096 Oct 21 00:06 testdir
八、Linux编程
1、vim编辑器
(1)Linux系统默认自带vi编辑器,但是vi编辑器使用比较困难,而vim是vi的增强版,在Ubuntu中,可使用命令"sudo apt-get install vim"安装vim编辑器。
(2)运行命令"vim <文件名>"可以用vim编辑器打开目标文件。
(3)vim的三种工作模式:
①一般模式(指令模式/普通模式):打开文件会默认进入该模式,在该模式下,用户不能直接输入文字编辑文件,不过可以通过键盘的上下左右键移动光标、复制文件内容,也可以使用指令编辑文件(常见的一般模式指令见下表)。
|------|-----------------------|
| 常用指令 | 作用 |
| dd | 删除光标所在行 |
| u | 撤销上一步的操作 |
| . | 重复上一步的操作 |
| yy | 复制光标所在行 |
| nyy | 复制光标所在行往下数的第n行,n为待定系数 |
| P | 复制从光标当前位置到上一行的内容 |
| p | 复制从光标当前位置到下一行的内容 |

②编辑模式(插入模式):在一般模式下,按下任一插入键即可进入该模式(常见的进入插入模式按键见下表),在该模式下,用户可以增加、修改、删除内容。按ESC键,即可退出编辑模式,回到一般模式。
|-----|---------------------------|
| 插入键 | 作用 |
| i | 在光标前面插入 |
| a | 在光标后面插入(常用) |
| I | 在本行开头插入 |
| A | 在本行末尾插入 |
| o | 在光标下方新开一行插入 |
| O | 在光标上方新开一行插入 |
| s | 删除光标指示的单个字符,然后在删除的位置插入 |
| r | 仅替换光标指示的单个字符,替换完后直接回到一般模式 |

③命令行模式(底行模式):在一般模式下,输入":"或者"/"或者"?"即可进入该模式,在该模式下,常用的命令如下表所示。
|-----------|---------------------|
| 常用命令 | 作用 |
| :w | 保存修改 |
| :q | 退出(所有修改保存才能使用该命令退出) |
| :wq | 保存修改并退出 |
| :q! | 退出,不保存修改 |
| :w! | 强制保存修改 |
| :set nu | 显示行号 |
| :set nonu | 取消显示行号 |
| /xxx | 在光标所在处向下查找字符串xxx |
| ?xxx | 在光标所在处向上查找字符串xxx |

(4)vim编辑器默认一个TAB键8个空格长度,需要修改为4个空格长度(更符合编程习惯),可以使用vim编辑器打开文件/etc/vim/vimrc(使用root的权限打开,否则无法修改),在此文件最后面输入代码"set ts=4",修改完成以后保存并关闭文件即可。

(5)vim编辑器默认不显示行号,为了避免每次编辑都输入命令显示行号的麻烦,可以使用vim编辑器打开文件/etc/vim/vimrc(使用root的权限打开,否则无法修改),在此文件最后面输入代码"set nu",修改完成以后保存并关闭文件即可。

2、Linux C程序编译器
(1)交叉编译指的是编译环境和程序最终运行的环境不是同一个平台。在开发SOC(片上系统,把一整套计算机系统的核心模块全部集成进一颗芯片中)时,SOC的性能弱、内存小,板子上通常跑不动gcc编译器,所以编译程序的任务需要在性能强的PC虚拟机上运行,用交叉编译器提前编译好二进制固件,再传到开发板上运行。
(2)如无特殊情况,本系列文章均以C语言编程为基础进行Linux系统的学习,在Linux环境下,可以使用gcc编译器编译C程序(实际上,gcc编译器还可以编译C++程序和汇编程序)。部分版本的Ubuntu安装时不带gcc编译器,需要另行下载,可运行指令"gcc -v"确认。
(3)gcc命令的格式和常见可选参数如下:
gcc 选项 <文件名> # 方括号表示可选参数,选项用"-"引出
|--------------|---------------------------------------------------|
| 选项 | 作用 |
| -c | 只编译,不链接为可执行文件,编译器将输入的.c文件编译为.o格式的目标文件 |
| -o <输出文件名> | 指定编译结束后输出的文件名,如果不指定文件名,则默认输出a.out |
| -g | 添加调试信息,如果要使用调试工具(GDB),就必须添加该选项,指示编译的时候生成调试所需的符号信息 |
| -O | 对程序进行优化编译,生成的可执行程序效率更高,但编译过程更慢 |
| -O2 | 对程序进行大幅度优化编译,生成的可执行程序效率更高,但编译过程更慢 |

(4)一条gcc命令其实是分4步进行编译的:
①预处理:展开#include,替换#define宏,删除注释,如果是编译.c文件则输出.i文件,如果是编译.cpp文件则输出.ii文件。
gcc -E main.c > main.i
gcc -E main.cpp > main.ii
②编译:经过语法分析、词法分析、语义分析和符号会中,把C/C++代码转换成汇编代码,结果保存在.s文件中。
gcc -S main.i
gcc -S main.ii
③汇编:把汇编代码转换为二进制/机器指令,结果保存在.o文件中。
gcc -c main.s
④链接:把多个.o文件合并(C++的链接还需要合并标准库libstdc++.so),以及符号表的重定位,生成可执行程序。
gcc main.o
gcc main.o -lstdc++
3、make工具与Makefile
关于Makefile的相关内容,可参考《makefile从入门到实战》,此处不过多赘述