目录
[1.1 GCC简介](#1.1 GCC简介)
[1.2 GCC基本用法](#1.2 GCC基本用法)
[1.3 常用编译选项](#1.3 常用编译选项)
[1.4 简单编译示例](#1.4 简单编译示例)
[2.1 编译过程概述](#2.1 编译过程概述)
[2.2 四个阶段详解](#2.2 四个阶段详解)
[2.2.1 预处理(Preprocessing)](#2.2.1 预处理(Preprocessing))
[2.2.2 编译(Compilation)](#2.2.2 编译(Compilation))
[2.2.3 汇编(Assembly)](#2.2.3 汇编(Assembly))
[2.2.4 链接(Linking)](#2.2.4 链接(Linking))
[2.3 完整编译流程图](#2.3 完整编译流程图)
[2.4 单步编译 vs 分步编译](#2.4 单步编译 vs 分步编译)
[3.1 GDB简介](#3.1 GDB简介)
[3.2 GDB基本用法](#3.2 GDB基本用法)
[3.3 GDB常用命令](#3.3 GDB常用命令)
[3.4 GDB调试示例](#3.4 GDB调试示例)
[3.5 GDB高级功能](#3.5 GDB高级功能)
[3.5.1 条件断点](#3.5.1 条件断点)
[3.5.2 观察点(Watchpoint)](#3.5.2 观察点(Watchpoint))
[3.5.3 多线程调试](#3.5.3 多线程调试)
[3.5.4 调试已运行的程序](#3.5.4 调试已运行的程序)
[3.6 GDB TUI模式(图形界面)](#3.6 GDB TUI模式(图形界面))
[4.1 进程概念](#4.1 进程概念)
[4.2 查看进程](#4.2 查看进程)
[4.3 进程状态](#4.3 进程状态)
[4.4 进程控制](#4.4 进程控制)
[4.4.1 前台与后台](#4.4.1 前台与后台)
[4.4.2 终止进程](#4.4.2 终止进程)
[4.4.3 进程优先级](#4.4.3 进程优先级)
[4.5 进程资源限制](#4.5 进程资源限制)
[4.6 守护进程管理](#4.6 守护进程管理)
[4.6.1 System V init(旧方式)](#4.6.1 System V init(旧方式))
[4.6.2 systemd(新方式)](#4.6.2 systemd(新方式))
[4.7 进程间通信(IPC)](#4.7 进程间通信(IPC))
[5.1 用户和组基础](#5.1 用户和组基础)
[5.2 用户管理命令](#5.2 用户管理命令)
[5.2.1 添加用户](#5.2.1 添加用户)
[5.2.2 删除用户](#5.2.2 删除用户)
[5.2.3 修改用户](#5.2.3 修改用户)
[5.2.4 设置密码](#5.2.4 设置密码)
[5.3 组管理命令](#5.3 组管理命令)
[5.3.1 添加组](#5.3.1 添加组)
[5.3.2 删除组](#5.3.2 删除组)
[5.3.3 修改组](#5.3.3 修改组)
[5.3.4 管理组成员](#5.3.4 管理组成员)
[5.4 用户信息查看](#5.4 用户信息查看)
[5.5 用户配置文件](#5.5 用户配置文件)
[5.5.1 /etc/passwd](#5.5.1 /etc/passwd)
[5.5.2 /etc/shadow](#5.5.2 /etc/shadow)
[5.5.3 /etc/group](#5.5.3 /etc/group)
[5.6 用户切换](#5.6 用户切换)
[5.7 sudo配置](#5.7 sudo配置)
[6.1 压缩格式对比](#6.1 压缩格式对比)
[6.2 gzip/gunzip](#6.2 gzip/gunzip)
[6.3 bzip2/bunzip2](#6.3 bzip2/bunzip2)
[6.4 xz/unxz](#6.4 xz/unxz)
[6.5 tar命令(打包)](#6.5 tar命令(打包))
[6.6 zip/unzip](#6.6 zip/unzip)
[6.7 7z](#6.7 7z)
[6.8 压缩命令速查表](#6.8 压缩命令速查表)
[7.1 基本区别](#7.1 基本区别)
[7.2 编译行为差异](#7.2 编译行为差异)
[7.2.1 编译C文件](#7.2.1 编译C文件)
[7.2.2 编译C++文件](#7.2.2 编译C++文件)
[7.3 链接差异](#7.3 链接差异)
[7.4 编译选项兼容性](#7.4 编译选项兼容性)
[7.5 使用建议](#7.5 使用建议)
[8.1 库的概念](#8.1 库的概念)
[8.2 静态库(Static Library)](#8.2 静态库(Static Library))
[8.2.1 特点](#8.2.1 特点)
[8.2.2 创建静态库](#8.2.2 创建静态库)
[8.2.3 使用静态库](#8.2.3 使用静态库)
[8.3 共享库/动态库(Shared Library)](#8.3 共享库/动态库(Shared Library))
[8.3.1 特点](#8.3.1 特点)
[8.3.2 创建共享库](#8.3.2 创建共享库)
[8.3.3 使用共享库](#8.3.3 使用共享库)
[8.4 库的管理命令](#8.4 库的管理命令)
[8.5 静态库与动态库对比](#8.5 静态库与动态库对比)
[8.6 库的版本控制](#8.6 库的版本控制)
[8.6.1 共享库版本命名](#8.6.1 共享库版本命名)
[8.6.2 创建带版本的共享库](#8.6.2 创建带版本的共享库)
[9.1 文件系统和目录](#9.1 文件系统和目录)
[Q1: Linux根目录下主要目录的作用?](#Q1: Linux根目录下主要目录的作用?)
[Q2: 什么是inode?](#Q2: 什么是inode?)
[Q3: 软链接和硬链接的区别?](#Q3: 软链接和硬链接的区别?)
[9.2 文件权限](#9.2 文件权限)
[Q4: chmod 777和chmod 755的区别?](#Q4: chmod 777和chmod 755的区别?)
[Q5: SUID、SGID、Sticky Bit的作用?](#Q5: SUID、SGID、Sticky Bit的作用?)
[Q6: 如何查找权限为777的文件并修改为755?](#Q6: 如何查找权限为777的文件并修改为755?)
[9.3 进程管理](#9.3 进程管理)
[Q7: 进程和线程的区别?](#Q7: 进程和线程的区别?)
[Q8: 什么是僵尸进程?如何产生和解决?](#Q8: 什么是僵尸进程?如何产生和解决?)
[Q9: 如何查看系统负载?](#Q9: 如何查看系统负载?)
[9.4 网络](#9.4 网络)
[Q10: TCP和UDP的区别?](#Q10: TCP和UDP的区别?)
[Q11: 如何查看端口占用?](#Q11: 如何查看端口占用?)
[9.5 Shell和脚本](#9.5 Shell和脚本)
[Q13: 如何调试Shell脚本?](#Q13: 如何调试Shell脚本?)
[9.6 编译和调试](#9.6 编译和调试)
[Q14: 静态库和动态库的区别?](#Q14: 静态库和动态库的区别?)
[Q15: 编译时提示"undefined reference"是什么原因?](#Q15: 编译时提示"undefined reference"是什么原因?)
[Q16: 什么是core dump?如何生成和分析?](#Q16: 什么是core dump?如何生成和分析?)
[9.7 系统管理](#9.7 系统管理)
[Q17: Linux启动流程?](#Q17: Linux启动流程?)
[Q18: 如何排查系统卡顿?](#Q18: 如何排查系统卡顿?)
[Q19: 什么是Linux命名空间(Namespace)?](#Q19: 什么是Linux命名空间(Namespace)?)
[Q20: 解释Linux的IO模型?](#Q20: 解释Linux的IO模型?)
前言
本文详细介绍了Linux系统开发中的核心工具和技术,主要内容包括:
- GCC/G++编译套件的使用方法和常见选项
- 程序编译链接的完整流程(预处理-编译-汇编-链接)
- GDB调试工具的使用技巧
- 进程管理和用户权限管理
- 文件压缩归档命令
- 静态库与动态库的创建和使用
- Linux常见面试题目解析
文章通过大量命令示例和对比表格,系统性地讲解了Linux开发环境中的关键知识点,既包含基础操作指南,也涉及高级调试技巧和系统管理方法,适合作为Linux开发的实用参考手册。
一、编译链接和GCC
1.1 GCC简介
GCC(GNU Compiler Collection)是GNU项目开发的编程语言编译器套件,支持C、C++、Objective-C、Fortran、Ada、Go等多种语言。
在Linux开发中,GCC是最常用的C/C++编译器。
1.2 GCC基本用法
bash
gcc [选项] [输入文件] [输出文件]
1.3 常用编译选项
| 选项 | 说明 |
|---|---|
-o <file> |
指定输出文件名 |
-c |
只编译不链接,生成目标文件(.o) |
-S |
只编译到汇编代码(.s) |
-E |
只进行预处理 |
-g |
生成调试信息,用于GDB调试 |
-O0 |
不进行优化(默认) |
-O1 |
基本优化 |
-O2 |
更多优化(推荐) |
-O3 |
最高级别优化 |
-Wall |
显示所有警告信息 |
-Werror |
将警告视为错误 |
-I<dir> |
指定头文件搜索路径 |
-L<dir> |
指定库文件搜索路径 |
-l<lib> |
链接指定的库文件 |
-static |
静态链接 |
-shared |
生成共享库 |
-fPIC |
生成位置无关代码(用于共享库) |
-D<macro> |
定义宏 |
-U<macro> |
取消定义宏 |
-v |
显示编译过程的详细信息 |
--version |
显示GCC版本 |
1.4 简单编译示例
bash
# 基本编译
gcc hello.c -o hello
# 分步编译
gcc -c hello.c -o hello.o # 编译成目标文件
gcc hello.o -o hello # 链接成可执行文件
# 包含调试信息
gcc -g hello.c -o hello
# 开启优化和警告
gcc -O2 -Wall hello.c -o hello
# 指定头文件路径
gcc -I./include hello.c -o hello
# 链接数学库
gcc math.c -o math -lm
# 链接自定义库
gcc main.c -o main -L./lib -lmylib
二、编译链接过程
2.1 编译过程概述
C/C++程序从源代码到可执行文件需要经过四个阶段:
bash
源代码(.c/.cpp) → 预处理 → 编译 → 汇编 → 链接 → 可执行文件
2.2 四个阶段详解
2.2.1 预处理(Preprocessing)
任务 :处理以#开头的预处理指令
处理内容:
- 宏展开(
#define) - 文件包含(
#include) - 条件编译(
#ifdef,#ifndef,#if等) - 删除注释
命令:
gcc -E hello.c -o hello.i # 生成预处理后的文件
示例:
bash
// hello.c
#include <stdio.h>
#define PI 3.14
#define SQUARE(x) ((x) * (x))
int main() {
printf("PI = %f\n", PI);
printf("Square of 5 = %d\n", SQUARE(5));
return 0;
}
预处理后:
bash
// 展开#include,插入stdio.h内容
// 展开宏PI和SQUARE
int main() {
printf("PI = %f\n", 3.14);
printf("Square of 5 = %d\n", ((5) * (5)));
return 0;
}
2.2.2 编译(Compilation)
任务:将预处理后的C代码翻译成汇编代码
工作内容:
- 语法分析
- 语义分析
- 代码优化
- 生成汇编代码
命令:
gcc -S hello.i -o hello.s # 生成汇编代码
gcc -S hello.c -o hello.s # 直接从源文件生成汇编
汇编代码示例(x86-64):
bash
.file "hello.c"
.text
.section .rodata
.LC0:
.string "PI = %f\n"
.LC1:
.string "Square of 5 = %d\n"
.text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
movl $5, %eax
imull $5, %eax
movl %eax, %esi
leaq .LC1(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
popq %rbp
ret
2.2.3 汇编(Assembly)
任务:将汇编代码翻译成机器码(二进制目标文件)
命令:
cpp
gcc -c hello.s -o hello.o # 生成目标文件
gcc -c hello.c -o hello.o # 直接从源文件生成目标文件
as hello.s -o hello.o # 使用汇编器
目标文件特点:
- 二进制格式(ELF格式在Linux上)
- 包含机器码,但还不能直接执行
- 包含符号表、重定位信息等
- 未解析外部符号引用
2.2.4 链接(Linking)
任务:将多个目标文件和库文件链接成可执行文件
工作内容:
- 符号解析:将符号引用与符号定义关联
- 重定位:调整代码和数据的地址
- 合并段:将多个目标文件的段合并
命令:
bash
gcc hello.o -o hello # 链接成可执行文件
gcc hello.o lib.a -o hello # 链接静态库
gcc hello.o -L. -lmylib -o hello # 链接动态库
ld hello.o -o hello -lc # 使用链接器直接链接
2.3 完整编译流程图
┌─────────────┐ 预处理 ┌─────────────┐
│ source.c │ ────────────> │ source.i │
│ (源代码) │ gcc -E │ (预处理文件) │
└─────────────┘ └─────────────┘
│
│ 编译
▼
┌─────────────┐
│ source.s │
│ (汇编代码) │
└─────────────┘
│
│ 汇编
▼
┌─────────────┐
│ source.o │
│ (目标文件) │
└─────────────┘
│
│ 链接
▼
┌─────────────┐ ┌─────────────┐
│ lib.a │ ────────────> │ program │
│ (静态库) │ │ (可执行文件) │
│ lib.so │ └─────────────┘
│ (动态库) │
└─────────────┘
2.4 单步编译 vs 分步编译
单步编译(适合小型项目)
gcc main.c utils.c -o program
分步编译(适合大型项目)
# 编译各个源文件
gcc -c main.c -o main.o
gcc -c utils.c -o utils.o
gcc -c helper.c -o helper.o
# 链接成可执行文件
gcc main.o utils.o helper.o -o program
分步编译的优势:
- 只重新编译修改过的文件,节省时间
- 便于并行编译
- 便于模块化管理和调试
三、GCC和GDB
3.1 GDB简介
GDB(GNU Debugger)是GNU项目的程序调试工具,用于调试C、C++等程序。
3.2 GDB基本用法
bash
# 编译时添加-g选项生成调试信息
gcc -g program.c -o program
# 启动GDB
gdb program
# 启动GDB并传递参数
gdb --args program arg1 arg2
# 调试core文件
gdb program core
# 附加到运行中的进程
gdb program <pid>
3.3 GDB常用命令
| 命令 | 简写 | 说明 |
|---|---|---|
run |
r |
运行程序 |
quit |
q |
退出GDB |
break |
b |
设置断点 |
continue |
c |
继续运行 |
step |
s |
单步执行(进入函数) |
next |
n |
单步执行(不进入函数) |
finish |
运行到函数返回 | |
until |
运行到指定行 | |
print |
p |
打印变量值 |
display |
每次停止时显示变量 | |
info |
显示信息 | |
backtrace |
bt |
显示调用栈 |
frame |
f |
切换栈帧 |
list |
l |
显示源代码 |
set |
设置变量值 | |
watch |
设置观察点 | |
delete |
d |
删除断点 |
enable |
启用断点 | |
disable |
禁用断点 | |
kill |
k |
终止程序 |
3.4 GDB调试示例
bash
# 1. 编译带调试信息的程序
gcc -g -O0 program.c -o program
# 2. 启动GDB
gdb program
# 3. 在GDB中操作
(gdb) break main # 在main函数设置断点
(gdb) break 25 # 在第25行设置断点
(gdb) break func # 在func函数设置断点
(gdb) info breakpoints # 查看所有断点
(gdb) run # 运行程序
(gdb) next # 单步执行(不进入函数)
(gdb) step # 单步执行(进入函数)
(gdb) print var # 打印变量值
(gdb) print/x var # 以十六进制打印
(gdb) display var # 每次停止都显示var
(gdb) continue # 继续运行到下一个断点
(gdb) backtrace # 查看调用栈
(gdb) frame 2 # 切换到第2层栈帧
(gdb) list # 显示源代码
(gdb) set var=10 # 设置变量值
(gdb) delete 1 # 删除1号断点
(gdb) quit # 退出GDB
3.5 GDB高级功能
3.5.1 条件断点
bash
break 10 if i == 5 # 当i等于5时才中断
break func if x > 10 # 条件断点
3.5.2 观察点(Watchpoint)
bash
watch var # 当变量被写入时中断
rwatch var # 当变量被读取时中断
awatch var # 当变量被读或写时中断
3.5.3 多线程调试
bash
info threads # 显示所有线程
thread 2 # 切换到线程2
break func thread 2 # 在指定线程设置断点
3.5.4 调试已运行的程序
bash
# 获取进程ID
ps aux | grep program
# 附加到进程
gdb program <pid>
# 或在GDB中
(gdb) attach <pid>
3.6 GDB TUI模式(图形界面)
bash
gdb -tui program # 启动TUI模式
在GDB中切换:
bash
Ctrl+X+A # 切换TUI模式
layout src # 显示源代码
layout asm # 显示汇编代码
layout split # 同时显示源码和汇编
四、进程管理
4.1 进程概念
进程(Process)是程序的一次执行实例,是系统进行资源分配和调度的基本单位。
进程与程序的区别:
- 程序是静态的代码和数据集合
- 进程是程序动态执行的过程
4.2 查看进程
bash
# 查看当前终端的进程
ps
# 查看所有进程详细信息
ps aux
# 标准格式显示
ps -ef
# 树形显示进程关系
ps auxf
pstree
# 动态显示进程状态
top
htop
# 查找特定进程
ps aux | grep nginx
pgrep nginx
pidof nginx
4.3 进程状态
| 状态 | 说明 |
|---|---|
R (Running) |
运行中或在运行队列中 |
S (Sleeping) |
可中断睡眠(等待事件) |
D (Disk sleep) |
不可中断睡眠(通常在进行I/O) |
T (Stopped) |
被信号停止 |
t (Tracing stop) |
被调试器停止 |
Z (Zombie) |
僵尸进程(已终止但未被回收) |
X (Dead) |
死亡进程 |
4.4 进程控制
4.4.1 前台与后台
bash
# 后台运行程序
./program &
# 将前台程序挂起(Ctrl+Z)
# 然后可以:
bg # 放到后台继续运行
fg # 放到前台继续运行
fg %1 # 将作业1放到前台
# 查看作业
jobs
jobs -l # 显示PID
4.4.2 终止进程
bash
kill PID # 发送TERM信号(默认15)
kill -9 PID # 强制终止(SIGKILL)
kill -15 PID # 正常终止(SIGTERM)
kill -1 PID # 重新加载配置(SIGHUP)
killall process_name # 按名称终止
pkill process_name # 按名称终止
xkill # 图形界面点击终止
常用信号:
| 信号 | 值 | 说明 |
|---|---|---|
| SIGHUP | 1 | 挂起信号,常用于重新加载配置 |
| SIGINT | 2 | 中断信号(Ctrl+C) |
| SIGKILL | 9 | 强制终止,不可捕获 |
| SIGTERM | 15 | 正常终止信号(默认) |
| SIGSTOP | 19 | 停止进程(Ctrl+Z) |
| SIGCONT | 18 | 继续执行 |
4.4.3 进程优先级
bash
# 以指定优先级运行程序(nice值:-20到19,越小优先级越高)
nice -n 10 ./program # nice值为10
# 修改运行中进程的优先级
renice -n 5 -p PID # 修改指定进程
renice -n 5 -u username # 修改用户所有进程
# 实时优先级(chrt)
chrt -f 99 ./program # FIFO实时调度,优先级99
4.5 进程资源限制
bash
# 查看资源限制
ulimit -a
# 设置资源限制
ulimit -c unlimited # core文件大小无限制
ulimit -n 4096 # 最大打开文件数
ulimit -u 1000 # 最大进程数
ulimit -v 1048576 # 虚拟内存限制(KB)
4.6 守护进程管理
4.6.1 System V init(旧方式)
bash
/etc/init.d/service start
/etc/init.d/service stop
/etc/init.d/service restart
/etc/init.d/service status
4.6.2 systemd(新方式)
bash
systemctl start service # 启动服务
systemctl stop service # 停止服务
systemctl restart service # 重启服务
systemctl reload service # 重新加载配置
systemctl status service # 查看状态
systemctl enable service # 开机自启
systemctl disable service # 取消开机自启
systemctl list-units --type=service # 列出所有服务
4.7 进程间通信(IPC)
Linux进程间通信方式:
| 方式 | 说明 |
|---|---|
| 管道(Pipe) | 父子进程间单向通信 |
| 命名管道(FIFO) | 无亲缘关系进程间通信 |
| 信号(Signal) | 异步通知机制 |
| 消息队列 | 消息的链表存储 |
| 共享内存 | 最快的IPC方式 |
| 信号量 | 同步机制 |
| 套接字(Socket) | 网络通信或本地通信 |
五、用户管理
5.1 用户和组基础
Linux是多用户操作系统,每个用户有唯一的UID(用户ID),每个组有唯一的GID(组ID)。
用户分类:
- root用户:超级用户,UID为0,拥有最高权限
- 系统用户:用于运行系统服务,UID通常1-999
- 普通用户:普通登录用户,UID通常1000+
5.2 用户管理命令
5.2.1 添加用户
bash
# 添加用户
useradd username
# 添加用户并设置家目录、shell等
useradd -m -s /bin/bash -c "Full Name" username
# 常用选项
useradd -m username # 创建家目录
useradd -d /home/myuser username # 指定家目录
useradd -s /bin/bash username # 指定登录shell
useradd -g groupname username # 指定主组
useradd -G group1,group2 username # 指定附加组
useradd -u 1001 username # 指定UID
5.2.2 删除用户
bash
userdel username # 删除用户(保留家目录)
userdel -r username # 删除用户及家目录
userdel -f username # 强制删除
5.2.3 修改用户
bash
usermod -c "New Name" username # 修改注释
usermod -d /new/home username # 修改家目录
usermod -m -d /new/home username # 修改家目录并移动文件
usermod -s /bin/zsh username # 修改shell
usermod -g newgroup username # 修改主组
usermod -G group1,group2 username # 修改附加组
usermod -aG groupname username # 添加附加组
usermod -u 1002 username # 修改UID
usermod -L username # 锁定用户
usermod -U username # 解锁用户
5.2.4 设置密码
bash
passwd # 修改当前用户密码
passwd username # 修改指定用户密码(root)
passwd -l username # 锁定用户密码
passwd -u username # 解锁用户密码
passwd -d username # 删除用户密码
passwd -e username # 强制下次登录修改密码
5.3 组管理命令
5.3.1 添加组
bash
groupadd groupname # 添加组
groupadd -g 1001 groupname # 指定GID
5.3.2 删除组
bash
groupdel groupname # 删除组
5.3.3 修改组
bash
groupmod -n newname oldname # 修改组名
groupmod -g 1002 groupname # 修改GID
5.3.4 管理组成员
bash
gpasswd -a username groupname # 添加用户到组
gpasswd -d username groupname # 从组中删除用户
gpasswd -A username groupname # 设置组管理员
gpasswd groupname # 设置组密码
5.4 用户信息查看
bash
# 查看当前用户
whoami # 显示当前用户名
id # 显示当前用户ID和组ID
id username # 显示指定用户信息
# 查看登录用户
who # 显示登录用户信息
w # 显示登录用户及活动
last # 显示最近登录记录
lastlog # 显示所有用户最后登录时间
# 查看用户信息文件
cat /etc/passwd # 用户账户信息
cat /etc/shadow # 用户密码(加密)
cat /etc/group # 组信息
cat /etc/gshadow # 组密码
5.5 用户配置文件
5.5.1 /etc/passwd
格式:用户名:密码:UID:GID:注释:家目录:Shell
root:x:0:0:root:/root:/bin/bash
user:x:1000:1000:User Name:/home/user:/bin/bash
5.5.2 /etc/shadow
格式:用户名:加密密码:最后修改日期:最小天数:最大天数:警告天数:不活动天数:过期日期:保留
root:$6$...:18000:0:99999:7:::
user:$6$...:18000:0:99999:7:::
5.5.3 /etc/group
格式:组名:密码:GID:成员列表
root:x:0:
users:x:100:user1,user2
5.6 用户切换
su # 切换到root(需要root密码)
su - # 切换到root并加载环境
su username # 切换到指定用户
su - username # 切换到指定用户并加载环境
sudo command # 以root权限执行命令
sudo -i # 切换到root shell
sudo -u username command # 以指定用户执行命令
5.7 sudo配置
# 编辑sudoers文件
visudo
# 或
vi /etc/sudoers
sudoers配置示例:
# 给用户sudo权限
username ALL=(ALL:ALL) ALL
# 给用户免密码sudo权限
username ALL=(ALL) NOPASSWD: ALL
# 给组sudo权限
%wheel ALL=(ALL) ALL
# 限制特定命令
username ALL=(root) /usr/bin/systemctl restart nginx
六、文件压缩命令
6.1 压缩格式对比
| 格式 | 特点 | 适用场景 |
|---|---|---|
.gz (gzip) |
压缩率高,单文件 | 日志压缩、单文件 |
.bz2 (bzip2) |
压缩率更高,速度较慢 | 需要更高压缩率 |
.xz (xz) |
最高压缩率,最慢 | 归档长期存储 |
.zip |
跨平台,支持多文件 | Windows交互 |
.tar |
打包不压缩 | 文件集合 |
.tar.gz/.tgz |
打包并gzip压缩 | 最常用 |
.tar.bz2 |
打包并bzip2压缩 | 需要高压缩率 |
.tar.xz |
打包并xz压缩 | 最高压缩率 |
.7z |
高压缩率,支持加密 | 7-Zip格式 |
.rar |
专有格式 | Windows常见 |
6.2 gzip/gunzip
bash
# 压缩文件(原文件被删除)
gzip file.txt # 生成file.txt.gz
gzip -k file.txt # 保留原文件
# 解压文件
gunzip file.txt.gz # 或 gzip -d file.txt.gz
# 查看压缩文件内容
zcat file.txt.gz # 输出到标准输出
zless file.txt.gz # 分页查看
zgrep "pattern" file.txt.gz # 搜索内容
# 压缩级别(1-9,默认6)
gzip -9 file.txt # 最高压缩率
gzip -1 file.txt # 最快压缩
6.3 bzip2/bunzip2
bash
# 压缩文件
bzip2 file.txt # 生成file.txt.bz2
bzip2 -k file.txt # 保留原文件
# 解压文件
bunzip2 file.txt.bz2 # 或 bzip2 -d file.txt.bz2
# 查看内容
bzcat file.txt.bz2
bzless file.txt.bz2
6.4 xz/unxz
bash
# 压缩文件
xz file.txt # 生成file.txt.xz
xz -k file.txt # 保留原文件
# 解压文件
unxz file.txt.xz # 或 xz -d file.txt.xz
# 查看内容
xzcat file.txt.xz
xzless file.txt.xz
6.5 tar命令(打包)
# 基本语法
tar [选项] [归档文件] [文件或目录...]
常用选项:
| 选项 | 说明 |
|---|---|
-c |
创建新归档 |
-x |
解压归档 |
-t |
列出归档内容 |
-v |
显示详细信息 |
-f |
指定归档文件名 |
-z |
使用gzip压缩/解压 |
-j |
使用bzip2压缩/解压 |
-J |
使用xz压缩/解压 |
-C |
指定解压目录 |
-p |
保留文件权限 |
--exclude |
排除文件 |
示例:
bash
# 创建tar归档(仅打包,不压缩)
tar -cvf archive.tar file1 file2 dir1
# 创建tar.gz归档
tar -czvf archive.tar.gz file1 file2 dir1
# 创建tar.bz2归档
tar -cjvf archive.tar.bz2 file1 file2 dir1
# 创建tar.xz归档
tar -cJvf archive.tar.xz file1 file2 dir1
# 列出归档内容
tar -tvf archive.tar
tar -tzvf archive.tar.gz
# 解压归档
tar -xvf archive.tar
tar -xzvf archive.tar.gz
tar -xjvf archive.tar.bz2
tar -xJvf archive.tar.xz
# 解压到指定目录
tar -xzvf archive.tar.gz -C /target/directory
# 排除特定文件
tar -czvf backup.tar.gz --exclude='*.log' --exclude='tmp/*' /home/user
# 只提取特定文件
tar -xzvf archive.tar.gz path/to/specific/file
6.6 zip/unzip
bash
# 压缩文件/目录
zip archive.zip file1 file2
zip -r archive.zip dir1 # 递归压缩目录
# 压缩并排除文件
zip -r archive.zip dir1 -x "*.log"
# 解压
unzip archive.zip
unzip archive.zip -d /target/dir # 解压到指定目录
# 列出内容
unzip -l archive.zip
# 更新压缩包
zip -u archive.zip newfile
# 删除压缩包中的文件
zip -d archive.zip file.txt
6.7 7z
bash
# 安装
sudo apt-get install p7zip-full
# 压缩
7z a archive.7z file1 dir1 # 添加文件到归档
7z a -t7z -m0=lzma2 archive.7z dir1 # 指定压缩方法
# 解压
7z x archive.7z # 完整路径解压
7z e archive.7z # 提取到当前目录
# 列出内容
7z l archive.7z
# 测试完整性
7z t archive.7z
6.8 压缩命令速查表
| 操作 | 命令 |
|---|---|
| 压缩单个文件 | gzip file |
| 解压.gz | gunzip file.gz |
| 打包目录 | tar -cvf archive.tar dir |
| 打包并gzip压缩 | tar -czvf archive.tar.gz dir |
| 打包并bzip2压缩 | tar -cjvf archive.tar.bz2 dir |
| 打包并xz压缩 | tar -cJvf archive.tar.xz dir |
| 解压tar.gz | tar -xzvf archive.tar.gz |
| 创建zip | zip -r archive.zip dir |
| 解压zip | unzip archive.zip |
七、GCC与G++区别
7.1 基本区别
| 特性 | GCC | G++ |
|---|---|---|
| 全称 | GNU C Compiler | GNU C++ Compiler |
| 默认语言 | C | C++ |
| 编译C文件 | ✅ | ✅ |
| 编译C++文件 | ⚠️ 可能链接失败 | ✅ |
| 默认链接库 | 不链接C++标准库 | 自动链接libstdc++ |
| 预定义宏 | __GNUC__等 |
__GNUG__、__cplusplus等 |
7.2 编译行为差异
7.2.1 编译C文件
bash
# 两种方式都可以编译C文件
gcc hello.c -o hello
g++ hello.c -o hello
7.2.2 编译C++文件
bash
# 推荐:使用g++编译C++
g++ hello.cpp -o hello
# 使用gcc编译C++需要手动链接C++库
gcc hello.cpp -o hello -lstdc++
7.3 链接差异
关键区别:g++会自动链接C++标准库,而gcc不会。
bash
// hello.cpp
#include <iostream>
int main() {
std::cout << "Hello" << std::endl;
return 0;
}
bash
# 使用g++(成功)
g++ hello.cpp -o hello # ✅ 自动链接libstdc++
# 使用gcc(失败)
gcc hello.cpp -o hello # ❌ 链接错误,找不到C++符号
# 使用gcc(成功,需手动指定)
gcc hello.cpp -o hello -lstdc++ # ✅ 手动链接C++库
7.4 编译选项兼容性
大多数编译选项在gcc和g++中是通用的:
bash
# 通用选项
gcc/g++ -o output file.c/cpp # 指定输出
gcc/g++ -c file.c/cpp # 只编译
gcc/g++ -g file.c/cpp # 调试信息
gcc/g++ -O2 file.c/cpp # 优化
gcc/g++ -Wall file.c/cpp # 显示警告
gcc/g++ -I./include file.c/cpp # 头文件路径
gcc/g++ -L./lib file.c/cpp # 库文件路径
gcc/g++ -lmylib file.c/cpp # 链接库
7.5 使用建议
| 场景 | 推荐命令 |
|---|---|
| 纯C项目 | gcc |
| C++项目 | g++ |
| 混合项目 | g++(可以处理C和C++) |
| 需要明确区分 | 使用gcc编译C,g++编译C++,最后统一链接 |
八、静态库与共享库
8.1 库的概念
库(Library)是一组可复用的函数和数据的集合,可以被多个程序共享使用。
库的优势:
- 代码复用
- 模块化开发
- 减少可执行文件大小(动态库)
- 便于更新和维护
8.2 静态库(Static Library)
8.2.1 特点
- 扩展名:
.a(Linux)、.lib(Windows) - 链接时:库的代码被完整复制到可执行文件中
- 运行时:不依赖库文件
- 优点:部署简单,无依赖问题
- 缺点:可执行文件大,多个程序重复占用内存,更新需重新编译
8.2.2 创建静态库
bash
# 1. 编译源文件为目标文件
gcc -c math_utils.c -o math_utils.o
gcc -c string_utils.c -o string_utils.o
# 2. 使用ar命令创建静态库
ar rcs libutils.a math_utils.o string_utils.o
# ar选项说明:
# r - 插入文件到归档
# c - 创建归档
# s - 创建索引
8.2.3 使用静态库
bash
# 方式1:直接指定库文件
gcc main.c libutils.a -o program
# 方式2:使用-L和-l选项
gcc main.c -L. -lutils -o program
# -L. 表示在当前目录查找库
# -lutils 表示链接libutils.a
8.3 共享库/动态库(Shared Library)
8.3.1 特点
- 扩展名:
.so(Linux)、.dll(Windows)、.dylib(macOS) - 链接时:只记录库的名称和符号信息
- 运行时:动态加载库文件
- 优点:可执行文件小,多个程序共享内存中的同一份库,更新方便
- 缺点:部署复杂,有依赖问题
8.3.2 创建共享库
bash
# 1. 编译源文件为位置无关代码(PIC)
gcc -fPIC -c math_utils.c -o math_utils.o
gcc -fPIC -c string_utils.c -o string_utils.o
# 2. 链接成共享库
gcc -shared -o libutils.so math_utils.o string_utils.o
# 一步完成
gcc -fPIC -shared -o libutils.so math_utils.c string_utils.c
8.3.3 使用共享库
bash
# 编译时链接
gcc main.c -L. -lutils -o program
# 运行时需要找到库文件
# 方式1:将库复制到系统库目录
sudo cp libutils.so /usr/lib/
sudo ldconfig
# 方式2:设置LD_LIBRARY_PATH
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./program
# 方式3:编译时指定运行时库路径
gcc main.c -L. -lutils -Wl,-rpath,'$ORIGIN' -o program
8.4 库的管理命令
bash
# 查看静态库内容
ar -t libutils.a # 列出成员
ar -x libutils.a # 提取成员
# 查看共享库依赖
ldd program # 查看程序依赖的共享库
ldd libutils.so # 查看共享库的依赖
# 查看共享库符号
nm -D libutils.so # 查看动态符号
readelf -s libutils.so # 查看符号表
objdump -T libutils.so # 查看动态符号
# 更新共享库缓存
sudo ldconfig # 更新/etc/ld.so.cache
sudo ldconfig -p # 显示缓存中的库
# 查看库搜索路径
cat /etc/ld.so.conf
cat /etc/ld.so.conf.d/*
8.5 静态库与动态库对比
| 特性 | 静态库 | 动态库 |
|---|---|---|
| 扩展名 | .a |
.so |
| 链接时机 | 编译时 | 运行时 |
| 文件大小 | 可执行文件大 | 可执行文件小 |
| 内存占用 | 每个程序独立 | 多个程序共享 |
| 部署 | 简单(无依赖) | 复杂(需处理依赖) |
| 更新 | 需重新编译 | 替换库文件即可 |
| 性能 | 略快(无动态链接开销) | 略慢 |
| 兼容性 | 好 | 可能有版本问题 |
8.6 库的版本控制
8.6.1 共享库版本命名
libname.so.X.Y.Z
X - 主版本号(不兼容的接口更改)
Y - 次版本号(向后兼容的功能添加)
Z - 修订号(向后兼容的问题修复)
8.6.2 创建带版本的共享库
# 编译带版本的共享库
gcc -fPIC -shared -Wl,-soname,libutils.so.1 \
-o libutils.so.1.0.0 math_utils.c
# 创建符号链接
ln -s libutils.so.1.0.0 libutils.so.1
ln -s libutils.so.1 libutils.so
# 安装到系统目录
sudo cp libutils.so.1.0.0 /usr/lib/
sudo ldconfig # 自动创建符号链接
九、常见面试题目
9.1 文件系统和目录
Q1: Linux根目录下主要目录的作用?
答:
/bin:基本用户命令/sbin:系统管理命令/etc:配置文件/home:普通用户家目录/root:root用户家目录/var:可变数据(日志、缓存)/usr:用户程序/tmp:临时文件
Q2: 什么是inode?
答:
- inode是Linux文件系统中的一个数据结构
- 存储文件的元数据(大小、权限、时间戳、数据块位置等)
- 每个文件对应一个唯一的inode号
- 使用
ls -i查看inode号,df -i查看inode使用情况
Q3: 软链接和硬链接的区别?
答:
| 特性 | 硬链接 | 软链接(符号链接) |
|---|---|---|
| 创建命令 | ln file hardlink |
ln -s file symlink |
| 指向 | inode | 文件路径 |
| 跨文件系统 | 不支持 | 支持 |
| 原文件删除 | 仍可访问 | 失效(悬空链接) |
| 类型 | 普通文件 | 特殊链接文件 |
| 占用空间 | 不额外占用 | 占用少量空间存路径 |
9.2 文件权限
Q4: chmod 777和chmod 755的区别?
答:
777=rwxrwxrwx:所有用户有读、写、执行权限755=rwxr-xr-x:所有者可读写执行,组和其他用户只能读和执行- 一般可执行程序用755,敏感文件用700或600
Q5: SUID、SGID、Sticky Bit的作用?
答:
- SUID(4):用户执行文件时临时获得文件所有者的权限,如passwd命令
- SGID(2):执行时获得文件所属组权限;对目录,新文件继承目录的组
- Sticky Bit(1):只有文件所有者或root能删除目录中的文件,如/tmp
Q6: 如何查找权限为777的文件并修改为755?
答:
find /path -type f -perm 777 -exec chmod 755 {} \;
# 或
find /path -type f -perm 777 | xargs chmod 755
9.3 进程管理
Q7: 进程和线程的区别?
答:
| 特性 | 进程 | 线程 |
|---|---|---|
| 资源占用 | 独立地址空间,资源多 | 共享进程资源,资源少 |
| 通信 | 需要IPC机制 | 直接共享内存 |
| 切换开销 | 大 | 小 |
| 崩溃影响 | 不影响其他进程 | 可能导致整个进程崩溃 |
| 创建 | fork() | pthread_create() |
Q8: 什么是僵尸进程?如何产生和解决?
答:
- 产生:子进程终止后,父进程没有调用wait/waitpid回收其资源
- 危害:占用进程表项,可能导致无法创建新进程
- 解决:
- 父进程调用wait/waitpid
- 杀死父进程,让init进程接管回收
- 使用信号处理函数自动回收
Q9: 如何查看系统负载?
答:
bash
uptime # 查看平均负载
top # 实时查看
vmstat 1 # 查看系统整体状态
sar -u 1 5 # CPU使用情况
9.4 网络
Q10: TCP和UDP的区别?
答:
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接 | 无连接 |
| 可靠性 | 可靠传输 | 不可靠 |
| 顺序 | 保证顺序 | 不保证 |
| 拥塞控制 | 有 | 无 |
| 开销 | 大(头部20字节) | 小(头部8字节) |
| 适用场景 | HTTP、FTP、SSH | DNS、视频流、游戏 |
Q11: 如何查看端口占用?
答:
netstat -tuln # 查看监听端口
ss -tuln # 新版替代netstat
lsof -i :80 # 查看特定端口
fuser 80/tcp # 查看占用端口的进程
9.5 Shell和脚本
Q12: Shell脚本中?、?、#、@、@、*的区别?
答:
$?:上条命令的退出状态码$#:传递给脚本的参数个数$@:所有参数,每个参数独立("$@"保留参数中的空格)$*:所有参数,作为一个整体("$*"将所有参数合并为一个字符串)$0:脚本名$1-$9:第1-9个参数$$:当前进程PID
Q13: 如何调试Shell脚本?
答:
bash -x script.sh # 显示执行过程
set -x # 在脚本中开启调试
set +x # 关闭调试
9.6 编译和调试
Q14: 静态库和动态库的区别?
答:见本文第8章详细对比。
Q15: 编译时提示"undefined reference"是什么原因?
答:
- 链接时找不到函数定义
- 可能原因:
- 未链接对应的库文件(-l选项)
- 库文件路径不正确(-L选项)
- 链接顺序问题(依赖库要放在被依赖库后面)
- 库文件中确实没有该函数定义
Q16: 什么是core dump?如何生成和分析?
答:
- core dump:程序崩溃时内存状态的快照文件
- 生成条件:
- 编译时加
-g选项 ulimit -c unlimited设置core文件大小
- 编译时加
- 分析 :
gdb program core,然后使用bt查看调用栈
9.7 系统管理
Q17: Linux启动流程?
答:
- BIOS/UEFI自检
- 加载引导程序(GRUB)
- 加载内核(kernel)
- 执行init/systemd
- 启动系统服务
- 进入登录界面
Q18: 如何排查系统卡顿?
答:
# 1. 查看系统负载
uptime
# 2. 查看CPU使用
top -bn1 | head
# 3. 查看内存使用
free -h
# 4. 查看磁盘I/O
iostat -x 1
# 5. 查看进程状态
ps aux --sort=-%cpu | head
# 6. 查看系统日志
journalctl -xe
Q19: 什么是Linux命名空间(Namespace)?
答:
- 用于隔离系统资源的机制
- 类型:PID、Network、Mount、UTS、IPC、User、Cgroup
- 是容器技术(Docker)的基础
Q20: 解释Linux的IO模型?
答:
- 阻塞IO:默认模式,等待数据准备好
- 非阻塞IO:立即返回,轮询检查
- IO多路复用:select/poll/epoll同时监控多个IO
- 信号驱动IO:数据准备好时发送信号
- 异步IO:数据直接复制到用户空间后通知
附录:常用命令速查表
文件操作
ls, cd, pwd, mkdir, rm, cp, mv, touch, cat, less, head, tail, find, grep
权限管理
chmod, chown, chgrp, umask, sudo, su
进程管理
ps, top, kill, killall, nice, nohup, jobs, fg, bg
用户管理
useradd, userdel, usermod, passwd, groupadd, id, who, w
网络
ifconfig/ip, ping, netstat/ss, wget, curl, ssh, scp
压缩
tar, gzip, bzip2, xz, zip, unzip
编译调试
gcc, g++, make, gdb, ldd, nm, objdump
系统信息
uname, hostname, df, du, free, uptime, dmesg
点击跳转回顾: Linux系统基础详解(一)https://blog.csdn.net/2402_82668550/article/details/159323701?spm=1001.2014.3001.5501