手把手教你Linux 打包压缩与 gcc 编译详解

引言

在 Linux 系统中,文件打包压缩和程序编译是两项必备技能。打包压缩让你能够高效地管理和传输文件,而理解编译过程则帮助你深入理解程序从源代码到可执行文件的完整旅程。

今天,我将通过详细的命令示例和底层原理讲解,带你掌握 tar/gzip 的使用和 GCC 编译的四个阶段。

第一部分:文件打包与压缩

一、为什么需要打包压缩?

场景 需求
软件发布 将多个文件/目录打包成一个文件
网络传输 减小文件体积,节省带宽
备份归档 将分散的文件整合保存
源码分发 Linux内核、开源软件都使用 tar.gz 格式

二、tar 命令------打包与解包

  1. 打包操作(只打包,不压缩)
bash 复制代码
# 基本语法
tar cvf 包名.tar 文件1 文件2 ...

# 参数说明:
# c:创建新包(create)
# v:显示详细过程(verbose)
# f:指定普通文件(file)

# 示例:将三个文件打包
tar cvf my.tar file main.c passwd

# 输出:
# file
# main.c
# passwd

# 打包后原文件仍保留,需要可手动删除

打包的内存理解:

  1. 解包操作
bash 复制代码
# 基本语法
tar xvf 包名.tar

# 参数说明:
# x:从包中释放文件(extract)
# v:显示详细过程
# f:指定普通文件

# 示例:解包 my.tar
tar xvf my.tar

# 输出:
# file
# main.c
# passwd

实用技巧:

  • 解包时会覆盖同名文件,建议先确认或备份

  • 解包后保留原 tar 包,可重复使用

三、gzip 命令------压缩与解压

  1. 压缩操作
bash 复制代码
# 基本语法
gzip 文件名.tar

# 效果:将 tar 包压缩为 .tar.gz 格式
# 压缩后体积显著减小(通常能减少 60%-80%)

# 示例:压缩 my.tar
gzip my.tar

# 生成:my.tar.gz(原 my.tar 被替换)

# 常见场景:
# - 网络下载的软件包:libevent-2.1.12-stable.tar.gz
# - Linux内核源码:linux-6.1.tar.gz

压缩效果对比:

文件 大小 说明
my.tar 10 MB 打包后
my.tar.gz 2.5 MB gzip压缩后
  1. 解压操作(两种方式)
cpp 复制代码
# 方式1:一步解压法(推荐)
tar zxf 压缩包名.tar.gz

# 参数 z:启用 gzip 解压功能

# 示例:
tar zxf my.tar.gz

# 方式2:分步解压法
# 第一步:解压(得到 .tar 文件)
gzip -d my.tar.gz    # 或 gunzip my.tar.gz
# 第二步:解包
tar xvf my.tar

# 实用建议:推荐使用一步法 tar zxf,效率更高

方法一:

方法二:

四、其他压缩格式

格式 压缩命令 解压命令
.tar.gz tar zcvf tar zxf
.tar.bz2 tar jcvf tar jxf
.tar.xz tar Jcvf tar Jxf
.zip zip -r unzip
bash 复制代码
# 打包并压缩一步完成(最常用)
tar zcvf archive.tar.gz dir/

# 参数组合:
# z:gzip压缩
# c:创建包
# v:显示过程
# f:指定文件

# 示例:将 src 目录打包压缩
tar zcvf src_backup.tar.gz src/

第二部分:GCC 编译过程详解

一、编译的四个阶段

bash 复制代码
源代码 (.c)
     │
     ▼
┌─────────────┐
│ 1. 预处理   │ gcc -E
│   展开宏、   │
│   处理#include│
└─────────────┘
     │
     ▼
   (.i 文件)
     │
     ▼
┌─────────────┐
│ 2. 编译     │ gcc -S
│   语法检查   │
│   生成汇编   │
└─────────────┘
     │
     ▼
   (.s 文件)
     │
     ▼
┌─────────────┐
│ 3. 汇编     │ gcc -c
│   转换为     │
│   机器指令   │
└─────────────┘
     │
     ▼
   (.o 文件)
     │
     ▼
┌─────────────┐
│ 4. 链接     │ gcc
│   合并文件   │
│   链接库     │
└─────────────┘
     │
     ▼
  可执行文件

二、阶段1:预处理(Preprocessing)

任务:

  • 展开所有宏定义(#define MAX 1010

  • 删除所有注释(///* */

  • 处理 #include 指令(将被包含文件内容插入)

  • 添加行号和文件名标识(用于调试)

  • 保留 #pragma 编译器指令

    bash 复制代码
    # 命令格式
    gcc -E main.c -o main.i
    
    # 示例
    gcc -E hello.c -o hello.i
    
    # 查看预处理结果
    cat hello.i
    
    # 现象:
    # - stdio.h 被展开,可能多达800多行
    # - 宏被替换
    # - 注释被删除
  • 预处理前后对比:

bash 复制代码
// hello.c(源代码,约50行)
#include <stdio.h>
#define MAX 10

int main() {
    int arr[MAX];
    // 这是一个注释
    printf("Hello\n");
    return 0;
}

mian.i三、阶段2:编译(Compilation)

任务:

  • 进行语法和语义检查(此阶段才会报语法错误!

  • 将预处理后的代码转换为汇编代码

    bash 复制代码
    # 命令格式
    gcc -S main.i -o main.s
    
    # 示例
    gcc -S hello.i -o hello.s
    
    # 查看汇编代码
    cat hello.s

    汇编代码示例(x86_64):

bash 复制代码
main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $48, %rsp
    movl    $10, -4(%rbp)
    leaq    .LC0(%rip), %rdi
    call    puts@PLT
    movl    $0, %eax
    leave
    ret

特点: 汇编代码与机器指令几乎一一对应,不同 CPU 体系结构需要不同的汇编代码。

四、阶段3:汇编(Assembly)

任务: 将汇编代码转换为机器指令(二进制)

bash 复制代码
# 命令格式
gcc -c main.s -o main.o

# 示例
gcc -c hello.s -o hello.o

# 查看二进制文件(十六进制)
hexdump -C hello.o | head -20

文件格式:

  • Linux:.o 文件(ELF 格式)

  • Windows:.obj 文件(PE 格式)

二进制内容示例:

bash 复制代码
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  01 00 3e 00 01 00 00 00  00 00 00 00 00 00 00 00  |..>.............|
00000020  00 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
...

五、阶段4:链接(Linking)

任务:

  • 将多个目标文件合并

  • 链接库函数(如 printf 的实现)

  • 生成最终的可执行文件

    bash 复制代码
    # 命令格式
    gcc main.o -o main
    
    # 示例
    gcc hello.o -o hello
    
    # 直接编译链接(一步完成)
    gcc hello.c -o hello
  • 链接的本质:

  • 文件大小对比:

    文件 大小 说明
    hello.c 150 B 源代码
    hello.i 800+ 行 预处理后
    hello.s 约 50 行 汇编代码
    hello.o 1.4 KB 目标文件
    hello 16 KB+ 可执行文件(链接库后)

六、完整编译流程示例

bash 复制代码
# 创建一个简单的C程序
cat > test.c << 'EOF'
#include <stdio.h>
#define MSG "Hello"

int main() {
    printf("%s, World!\n", MSG);
    return 0;
}
EOF

# 1. 预处理
gcc -E test.c -o test.i

# 2. 编译
gcc -S test.i -o test.s

# 3. 汇编
gcc -c test.s -o test.o

# 4. 链接
gcc test.o -o test

# 运行
./test
# 输出:Hello, World!

# 一步到位
gcc test.c -o test

第三部分:库函数与头文件的关系

一、声明与实现分离

bash 复制代码
// 头文件(声明):stdio.h
// 位置:/usr/include/stdio.h
int printf(const char *format, ...);

// 库文件(实现):libc.so
// 位置:/lib/x86_64-linux-gnu/libc.so.6
// 包含 printf 的实际二进制代码

工作流程:

二、常用库的链接选项

链接选项 说明
C标准库 默认链接 printfscanf
数学库 -lm sqrtsincospow
线程库 -lpthread pthread_create
实时库 -lrt 定时器、共享内存
bash 复制代码
# 使用数学库需要显式链接
gcc math.c -o math -lm

# 使用线程库
gcc thread.c -o thread -lpthread

第四部分:知识小结

一、打包压缩命令速查

操作 命令 说明
打包 tar cvf out.tar file1 file2 仅打包,不压缩
解包 tar xvf out.tar 释放打包文件
gzip压缩 gzip file.tar 压缩为 .tar.gz
gzip解压 gzip -d file.tar.gz 解压为 .tar
一步压缩 tar zcvf out.tar.gz dir/ 打包+压缩
一步解压 tar zxf out.tar.gz 解压+解包

二、GCC编译阶段速查

阶段 命令 输入 输出 主要任务
预处理 gcc -E .c .i 展开宏、处理头文件
编译 gcc -S .i .s 语法检查、生成汇编
汇编 gcc -c .s .o 转换为机器指令
链接 gcc .o 可执行文件 合并文件、链接库

三、参数汇总

参数 作用 使用阶段
-E 只预处理 预处理
-S 生成汇编代码 编译
-c 只汇编,不链接 汇编
-o 指定输出文件名 所有阶段
-I 指定头文件路径 预处理
-L 指定库文件路径 链接
-l 链接指定库 链接
-g 生成调试信息 编译
-O2 优化级别2 编译

打包压缩和程序编译是 Linux 开发中的基础技能。

打包压缩核心:

  • tar 负责打包(多个文件变一个)

  • gzip 负责压缩(大文件变小)

  • tar zcvftar zxf 是最常用的组合

编译过程核心:

  • 预处理 → 编译 → 汇编 → 链接

  • 语法错误在编译阶段报出

  • 链接错误通常是找不到函数实现

相关推荐
A小辣椒10 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒14 小时前
TShark:基础知识
linux
AlfredZhao16 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao1 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质2 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式