Linux基础1
1. gcc的编译过程
gcc
是一套广泛应用于编译C语言、C++等多种语言的工具链,它的编译过程不是一步完成是,而是通过四个独立且有序的阶段将源代码最终转换为执行文件,每个阶段都有明确的功能和输出文件。
四个阶段分别是:预处理→编译→汇编→链接
预处理
预处理是指对源代码的预处理指令以#
开头,比如#include
、#define
、ifdef
等进行解析,生成“纯净的”预处理后代码。
- 处理
#include
:将头文件(如stdio.h
)的内容直接插入到文件中; - 处理
#define
:替换宏定义(如#define PI 3.14
会将代码中所有PI替换为3.14
; - 预处理条件编译(
#ifdef
/ifndef
/#endif
):根据条件保留或删除部分代码; - 删除注释:去除源代码中的注释,比如
//
和/*...*/
(多行注释),避免干扰后续编译。
输入文件为.c
文件
输出文件为.i
文件
关键指令:gcc -E main.c -o main.i
(-E
表示 “仅执行预处理阶段,结束后停止”)
编译
编译是指将预处理的代码转为汇编语言
对预处理后的代码.i
文件进行语法分析、语义分析、优化,最终将高级的C语言代码转换为对应平台的汇编语言代码。
- 语法分析:代码检查是否符合C语言语法规则,比如关键字错误,括号不匹配等问题,如果出现语法错误会报错;
- 语义分析:检查代码的逻辑合理性,比如变量的定义、类型不匹配等问题;
- 中间优化:对代码进行初步优化,比如常量折叠、死代码删除等,以提高后续汇编代码的效率
输入文件:.i
文件(预处理后的文件)
输出文件:.s
文件(汇编语言文件)
关键指令:gcc -s mian.i -o mian.s
(-s
表示“执行预处理+编译阶段,生成汇编代码后停止”)
汇编
汇编指的是将汇编代码转换为机器代码
将汇编语言代码(.s
)文件翻译为CPU可直接识别机器码(二进制指令),并封装为“目标文件”
输入文件:.s
文件(汇编语言文件)
输出文件:.o
文件(目标文件)(Windows下通常为.obj
)
关键指令:gcc -c main.s -o mian.o
(-c
表示"执行预处理+编译+汇编阶段,生成目标文件后停止")
注意:目标文件是“部分编译产物”,若代码中调用了外部函数,比如printf函数,来自标准库,此时仅仅只是记录了函数名,位关联实际实现地址。
链接
链接指的是整合目标文件库,生成可执行文件
将代码的目标文件(如main.o
)与依赖的库文件(如标准库libc.so
、第三方库)进行整合,解决函数/变量的“地址引用”问题,最终生成可执行文件)
- 静态链接:将库文件的代码直接连接复制到可执行文件中(生成的文件体积大,但不依赖外部库,可以独立执行);
- 动态链接:仅在可执行文件记录“库的引用信息”,运行时才加载库文件(生成的文件体积小,但依赖外部库,若库缺失则无法运行)
输入文件:.o
文件+依赖库文件(如libc.so
)
输出文件:可执行文件(Linux下默认无后缀,Windows下位.exe
)
关键指令:gcc mian.o -o main
总结:
源代码到可执行文件的流程
mian.c
(源代码)→(预处理)→mian.i
→(编译)→main.s
→(汇编)→mian.o
→(链接)→main
Linux文件类型
Linux文件分为类型并非通过扩展名来区分,而是通过文件本身的原数据来定义。Linux文件主要分为:普通文件、目录文件、链接文件(软链接和硬链接)、套接字文件、管道文件、块设备文件、字符设备文件七大类。
其中常用的文件类型分为以下几种:
- 普通文件
- 标识:在
ls -l
指令下以-
开头的文件 - 说明:最常见的文件类型,用于存储文本、二进制数据、程序代码等、
- 示例:文本文件(
.tex
)、可执行程序、图片文件等 - 特点:不包含文件系统的结构信息,仅存储实际数据
- 标识:在
- 目录文件
- 标识:在
ls -l
指令下以d
开头的文件 - 说明:用于管理文件和字目录的特殊文件,本质是存储文件名与对应inode的映射关系
- 示例:可以嵌套包含其他目录(形成目录树),每个目录至少包含
.
(当前目录)和..
父目录
- 标识:在
- 符号链接(软连接)
- 标识:在
ls -l
指令下以l
开头的文件 - 说明:类似Windows的快捷方式,是指向另一个文件/目标的引用
- 示例:
ln -s /user/local/bin/cplusplus cpp
- 特点:
- 可以跨文件系统创建
- 若源文件被删除,软连接会失效(显示“断链”)
- 大小通常是源文件路径的字符长度
- 标识:在
- 硬链接
- 标识:无特殊标识,在
ls ls
指令下以普通文件-
或目录d
- 说明:与源文件共享同一个
inode
的另一个文件名,本质是inode
的多个“别名” - 示例:
in file.txt file_link
创建的硬链接 - 特点:
- 不能跨文件系统创建
- 源文件删除后,硬链接仍然可以正常访问(因为
inode
没有被删除) - 不能对目录创建硬链接(避免目录树循环)
- 标识:无特殊标识,在
- 管道文件
- 标识:在
ls -l
命令输出中以p
开头 - 说明:用于进程间通信(IPC)临时文件,遵循“先进先出”(FIFO)原则
- 示例:
mkfifo mypipe
创建的命名管道 - 特点:
- 数据写入后被读取立即删除,不持久存储
- 常用于命令行中,连接进程
- 标识:在
- 字符设备文件
- 标识:在
ls -l
命令输出以c
开头 - 说明:用于与字符设备(按字节流交互的设备)通信的接口文件
- 示例:
/dev/tty
(终端设备),/dev/zero
(零字节生成器) - 特点:数据传输以字节为单位,不缓存数据
- 标识:在
- 块设备文件
- 标识:在
ls -l
命令输出以b
开头 - 说明:用于与块设备(按固定大小交互设备)通信的接口文件
- 示例:
/dev/sda
(硬盘)、/dev/nvme01
(NVMe固态硬盘) - 特点:数据传输以块为单位,支持随机访问,有缓存机制
- 标识:在
- 套接字文件
- 标识:在
ls -l
命令输出中以s
开头 - 说明:用于进程间网络通信的特殊文件,支持本地和网络套接字
- 示例:
/var/run/docker.sock
(Docker 守护进程套接字) - 特点:是网络编程(如 TCP/IP、UDP)的基础,可实现跨主机进程通信
- 标识:在