秋招学习至此,再补一点Linux知识,并对常用命令分类后按表格展示,方便以后使用。
1. Linux系统解析
Linux作为一款开源、稳定且高效的类Unix操作系统,自1991年由Linus Torvalds首次发布以来,已从个人项目发展为全球技术生态的核心支柱。其内核(Kernel)负责硬件抽象与资源调度,而完整的操作系统则由内核、GNU工具链及各类软件包组成(通常称为“发行版”,如Ubuntu、CentOS、Debian)。Linux的核心哲学是“一切皆文件”,将设备、目录甚至进程抽象为文件节点,极大简化了系统管理。凭借高安全性、低资源占用和强大的可定制性,Linux广泛应用于服务器集群(全球90%以上的超级计算机运行Linux)、云计算平台(如AWS EC2)、嵌入式系统(路由器、智能设备)及开发环境。尤其在命令行界面(CLI)下,用户能通过简洁的指令高效完成复杂任务,这不仅是系统管理员的必备技能,也是开发者提升效率的关键工具。
相比于图形界面,命令行有着以下优势:
- 效率:批量操作(如
find /logs -name "*.log" | xargs rm
一键清理日志)远超GUI点击。 - 可脚本化:命令可写入Shell脚本(.sh文件),实现自动化运维(如每日备份任务)。
- 远程管理:通过SSH连接服务器时,CLI是唯一可行方式(尤其带宽受限场景)。
1.1 Linux内核架构与设计哲学
1.宏内核架构与模块化设计
Linux采用宏内核(Monolithic Kernel)架构,与微内核(如Minix)不同,其核心服务(进程调度、内存管理、文件系统等)均运行在内核空间(特权模式),而非用户空间的服务进程中。这种设计牺牲了部分模块化优势,但极大提升了系统性能(避免了频繁的用户/内核态切换)。
关键特性:
- 动态可加载内核模块(LKM):通过
insmod
/modprobe
命令在运行时动态加载/卸载驱动或功能模块(如ext4.ko
文件系统模块),既保持了宏内核性能,又实现了功能扩展性。 - 系统调用接口(Syscall):用户空间程序通过
syscall
指令(x86-64架构)或int 0x80
(旧架构)触发软中断,进入内核态执行特权操作。例如open()
系统调用对应内核中的sys_open()
函数。
// Linux内核中系统调用的典型实现(简化版)
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
return do_sys_open(AT_FDCWD, filename, flags, mode);
}
2."一切皆文件"的实现机制
Linux将设备、套接字、甚至进程信息抽象为虚拟文件,通过虚拟文件系统(VFS) 统一接口实现。VFS定义了file_operations
、inode_operations
等结构体,作为底层文件系统(如ext4、procfs)的抽象层。
底层原理:
-
VFS四要素:
- 超级块(super_block):描述文件系统整体信息(块大小、inode数量等)
- 索引节点(inode):存储文件元数据(权限、大小、数据块指针)
- 目录项(dentry):缓存路径名到inode的映射,加速路径解析
- 文件对象(file):表示进程打开的文件实例(含读写位置)
-
设备文件实现:
/dev/sda
(块设备)对应block_device
结构,通过register_blkdev()
注册;
/dev/ttyS0
(字符设备)通过cdev_init()
和cdev_add()
注册为字符设备。
实例:访问
/proc/cpuinfo
时,VFS调用procfs的read()
方法,该方法直接从内核数据结构cpuinfo_x86
中提取信息,而非读取物理文件。
1.2 进程管理:从fork到调度
1. 进程创建与生命周期
fork()系统调用:
通过写时复制(Copy-on-Write, CoW) 技术高效创建子进程。父进程页表项标记为只读,当任一进程尝试写入时触发缺页异常,内核此时才复制物理页。
// 内核中fork()的关键路径(简化)
struct task_struct *copy_process(...)
{
struct task_struct *p;
p = dup_task_struct(current); // 复制task_struct
copy_thread(...); // 复制线程信息
copy_files(...); // 复制文件描述符表(引用计数+1)
copy_mm(...); // 复制内存描述符(CoW机制)
return p;
}
execve()系统调用:
加载新程序替换当前进程镜像,涉及:
- 解析ELF文件头(
/lib/ld-linux.so
为动态链接器) - 建立新的虚拟内存布局(代码段、数据段、堆、栈)
- 覆盖原进程的页表
2. 完全公平调度器(CFS)
Linux 2.6.23引入的CFS是基于红黑树的调度算法,核心思想是"完全公平"——按权重分配CPU时间。
关键数据结构:
- vruntime(虚拟运行时间):
vruntime = 实际运行时间 * (NICE_0_LOAD / 权重)
优先级高的进程权重更大,相同实际时间下vruntime增长更慢,从而获得更多调度机会。 - 红黑树(cfs_rq->tasks_timeline):
按vruntime排序,最左侧节点为下一个运行的进程。
调度触发时机:
- 时钟中断:当前进程时间片用尽(
timer_interrupt()
→scheduler_tick()
) - 自愿让出CPU:
sleep()
、wait()
等系统调用 - 抢占:高优先级进程唤醒(
try_to_wake_up()
触发resched_curr()
)
性能优化:CFS使用组调度(cgroup) 隔离资源,确保容器/用户组间公平分配CPU。
1.3 内存管理:虚拟地址到物理页的映射
1.分页机制与TLB加速
Linux采用四级页表(x86-64架构)实现虚拟地址到物理地址的转换:
虚拟地址 → PML4 → PDPT → PDE → PTE → 物理页帧
- PML4 (Page Map Level 4):
第4级页表,包含512个PML4E(PML4 Entries),每个指向一个PDPT。
物理地址来源:CR3寄存器提供PML4表的基地址。 - PDPT (Page Directory Pointer Table):
第3级页表,包含512个PDPTE,每个指向一个PDE表。
物理地址来源:PML4E中的物理页帧号(PFN)左移12位。 - PDE (Page Directory Entry):
第2级页表,包含512个PDE,每个指向一个PTE表(或2MB大页)。
物理地址来源:PDPTE中的PFN左移12位。 - PTE (Page Table Entry):
第1级页表,包含512个PTE,每个直接指向4KB物理页帧。
物理地址来源:PDE中的PFN左移12位。 - 页表项(PTE)结构:
包含物理页帧号(PFN)、访问位(Accessed)、脏位(Dirty)、写保护位(Write Protect)等标志。 - TLB(Translation Lookaside Buffer):
CPU缓存最近使用的页表项,缺失时触发页表遍历(硬件自动完成)。
2.内存分配策略
-
Slab分配器:
针对内核对象(如task_struct
、inode
)的高速缓存,避免频繁调用伙伴系统。struct kmem_cache *task_cache = kmem_cache_create("task_struct", sizeof(struct task_struct), ...); struct task_struct *tsk = kmem_cache_alloc(task_cache, GFP_KERNEL);
-
伙伴系统(Buddy System):
管理物理页帧,通过2^n大小的块合并/拆分减少碎片。例如请求3页时,系统分配4页(2^2)。 -
页框回收(kswapd):
当空闲内存低于/proc/sys/vm/min_free_kbytes
时,内核线程kswapd
触发回收:- 回收页缓存(Page Cache)
- 回收匿名页(通过Swap)
- OOM Killer(极端情况)
3.内存映射与共享
- mmap()系统调用:
将文件或设备映射到进程地址空间,避免用户/内核态数据拷贝。
cat
命令读取大文件时,内核直接将文件页缓存映射到用户空间。 - 匿名映射:
malloc()
小内存走brk()
,大内存(>128KB)走mmap()
,减少堆碎片。
1.4 文件系统:从inode到持久化存储
1.Ext4文件系统核心结构
-
块组(Block Group):
磁盘被划分为多个块组,每个组包含:- 超级块(Superblock):文件系统全局信息(备份在多个块组中)
- 块组描述符表(GDT):记录各块组状态
- inode表:存储文件元数据(每个inode 256字节)
- 数据块:存储文件内容
-
Extent树:
Ext4用Extent替代传统间接块指针,一个Extent可描述连续的物理块范围(如[逻辑块100-200] → [物理块5000-5100]),大幅提升大文件性能。
2.页缓存(Page Cache)与写回机制
- 读操作:
read()
系统调用优先从页缓存读取,缺失时触发读I/O(page_cache_sync_readahead
预读)。 - 写操作:
- Buffered I/O:先写入页缓存,由
pdflush
线程定期回写(默认30秒) - Direct I/O:绕过页缓存(
O_DIRECT
标志),用于数据库等场景
- Buffered I/O:先写入页缓存,由
- 写屏障(Barrier):
确保元数据与数据写入顺序(如先写数据块,再更新inode),防止断电导致文件系统损坏。
1.5 设备驱动与I/O栈
1.块设备I/O调度层
Linux I/O栈从上到下:
应用程序 → VFS → 通用块层(Generic Block Layer) → I/O调度器 → 设备驱动 → 硬件
I/O调度器选项:
- CFQ(Completely Fair Queuing):为进程分配I/O带宽(已弃用)
- Deadline:为读请求设置超时,防止饥饿
- NOOP:简单FIFO队列,适合SSD
- Kyber:针对NVMe优化的调度器(Linux 4.12+)
电梯合并(Elevator Merge):
调度器将相邻的I/O请求合并为单个请求,减少磁盘寻道。例如:
[读块10] + [读块11] → 合并为[读块10-11]
2.异步I/O与多队列支持
- 多队列块层(blk-mq):
Linux 3.13引入,为每个CPU核心创建独立请求队列,消除锁竞争,充分发挥NVMe并行能力。 - io_uring:
Linux 5.1新增的高性能异步I/O接口,通过共享内存环形缓冲区避免系统调用开销,吞吐量比aio
高10倍。
1.6 网络子系统:从Socket到网卡
1.TCP/IP协议栈实现
- Socket层:
struct socket
封装协议族(AF_INET)和类型(SOCK_STREAM),通过inet_stream_ops
绑定TCP操作。 - TCP状态机:
内核维护struct tcp_sock
,实现三次握手(TCP_SYN_RECV
→TCP_ESTABLISHED
)和拥塞控制(CUBIC算法)。 - 零拷贝技术:
- sendfile():直接从文件页缓存到网络缓冲区
- splice():通过管道实现用户态零拷贝
2.网络数据包处理
- 网卡中断:数据包到达触发硬中断(
__do_irq
) - 软中断(NET_RX):
napi_gro_receive()
处理包(支持GRO合并) - 协议栈处理:IP层(
ip_rcv
)、TCP层(tcp_v4_rcv
) - Socket队列:数据放入
sk_receive_queue
,唤醒用户进程
性能优化:
- RSS(Receive Side Scaling):多队列网卡将包分发到不同CPU
- XDP(eXpress Data Path):在驱动层处理包,延迟<1μs
1.7 系统启动流程:从BIOS到systemd
1.内核初始化关键步骤
- 解压内核:
arch/x86/boot/compressed/head_64.S
执行自解压 - 设置页表:开启分页模式(
__startup_64
) - 初始化子系统:
rest_init()
创建kernel_thread
(pid=2)kernel_init()
挂载根文件系统,启动用户空间init
2.systemd启动流程
1. systemd (PID 1) → 2. 加载单元文件(.service/.target) → 3. 并行启动服务
- 关键特性:
- Cgroups集成:每个服务运行在独立cgroup中
- 依赖管理:通过
Wants
/Requires
声明依赖关系 - 套接字激活:按需启动服务(如sshd)
2. 常用命令分类
以下命令基于Bash Shell(Linux默认Shell),按功能分类说明。重要提示:执行命令前务必确认参数,避免误操作(如rm -rf /
将删除全盘数据)。
2.1 文件与目录操作
命令 | 示例 | 功能说明 | 典型场景 |
---|---|---|---|
ls |
ls -lh /var/log |
列出目录内容:-l 显示详细权限/大小,-h 以KB/MB人性化显示,-a 包含隐藏文件(以. 开头) |
快速查看日志目录大小及修改时间 |
cd |
cd ~/projects |
切换目录:~ 代表用户主目录,.. 返回上级目录 |
开发时快速跳转到项目文件夹 |
mkdir |
mkdir -p data/{2023,2024} |
创建目录:-p 递归创建多级目录(自动补全缺失父目录) |
生成年份归档目录结构 |
cp |
cp -r /src /backup/ |
复制文件/目录:-r 递归复制目录,-v 显示详细过程 |
备份配置文件前先复制到安全位置 |
mv |
mv old.txt new.txt |
移动或重命名文件(移动操作不占用额外磁盘空间) | 重命名日志文件或迁移数据 |
rm |
rm -i *.tmp |
删除文件:-i 交互确认(防误删),慎用-rf (强制递归删除无提示) |
清理临时文件时避免误删重要数据 |
find |
find / -name "*.conf" 2>/dev/null |
按名称/类型搜索:2>/dev/null 忽略权限错误 |
定位丢失的配置文件 |
grep |
grep "ERROR" /var/log/syslog |
文本过滤:-i 忽略大小写,-r 递归目录搜索 |
从日志中快速筛选错误信息 |
2.2 权限与用户管理
Linux文件权限分为三类:用户(User)
、组(Group)
、其他(Others)
,每类包含读(r=4)
、写(w=2)
、执行(x=1)
。
例如:chmod 755 script.sh
→ 用户权限=7(rwx),组权限=5(rx),其他用户=5(rx)。
命令 | 示例 | 功能说明 |
---|---|---|
chmod |
chmod g+w file 给组添加写权限 |
修改权限 |
chown |
chown alice:devs file → 所有者为alice,组为devs |
更改所有者 |
sudo |
sudo apt update 以root身份更新软件包 |
临时提权 |
useradd /passwd |
sudo useradd -m bob 创建带主目录的用户 |
创建用户并设密码 |
2.3 系统监控与诊断
命令 | 示例 | 功能说明 |
---|---|---|
top |
top -c |
实时监控CPU/内存:-c 显示完整命令,P 按CPU排序,M 按内存排序 |
htop |
htop (需安装) |
增强版top ,支持鼠标操作和树状进程视图 |
df |
df -hT |
查看磁盘空间:-h 人性化显示,-T 显示文件系统类型(如ext4) |
du |
du -sh /var/log |
统计目录大小:-s 汇总,-h 人性化显示 |
journalctl |
journalctl -u nginx --since "2023-10-01" |
查看系统日志:过滤Nginx服务自指定日期的日志 |
lsof |
lsof -i :80 |
列出打开的网络连接:检查80端口占用进程(常用于排查端口冲突) |
故障排查流程:
- 用
df -h
确认磁盘是否满载- 用
du -sh /var/*
定位大目录- 用
lsof
查占用进程- 用
journalctl
分析错误日志
2.4 网络操作命令
命令 | 示例 | 功能说明 |
---|---|---|
ping |
ping google.com |
测试连通性 |
ifconfig /ip |
ip addr show 替代老旧ifconfig |
查看IP配置 |
netstat |
netstat -tuln 列出监听端口 |
网络状态统计 |
curl |
curl -I https://example.com 获取HTTP头信息 |
数据传输 |
ssh |
ssh user@192.168.1.100 |
安全远程登录 |
2.5 文本处理与管道艺术
命令 | 示例 | 功能说明 |
---|---|---|
cat |
cat /etc/os-release 查看系统版本 |
显示文件 |
less |
比more 更灵活,支持向前翻页 |
分页浏览大文件 |
sed |
sed 's/foo/bar/g' file 全局替换文本 |
流编辑器 |
awk |
awk '{print $1}' access.log 提取日志首列IP |
文本分析 |
管道(| ) |
ps aux |grep nginx 列出所有进程并过滤含nginx的行 |
组合命令 |
2.6 压缩与解压命令
命令 | 语法示例 | 功能说明 | 典型场景 |
---|---|---|---|
tar |
tar -czvf backup.tar.gz /data |
创建gzip压缩包:-c 创建,-z gzip压缩,-v 详细输出,-f 指定文件名 |
定期备份用户数据目录 |
tar |
tar -xzvf backup.tar.gz |
解压gzip压缩包:-x 解压,-z gzip,-v 详细,-f 指定文件 |
恢复误删文件 |
gzip |
gzip logfile.log |
压缩文件为.gz格式(原文件被删除) | 压缩旧日志文件节省磁盘空间 |
gunzip |
gunzip logfile.log.gz |
解压.gz文件(恢复原文件名) | 读取压缩归档日志 |
zip |
zip -r project.zip /project |
递归压缩目录为.zip格式 | 打包项目代码便于分享 |
unzip |
unzip project.zip |
解压.zip文件 | 安装第三方软件包 |
2.7 进程管理命令
命令 | 示例 | 功能说明 | 典型场景 |
---|---|---|---|
ps |
ps aux \| grep nginx |
查看进程:a 所有终端,u 用户格式,x 无终端进程,管道过滤 |
检查Web服务器进程是否运行 |
kill |
kill -15 1234 |
终止进程:-15 发送SIGTERM(优雅终止),-9 强制终止(慎用) |
关闭占用过高CPU的进程 |
top |
top -p 1234 |
监控指定进程:-p 后接PID |
实时观察特定进程资源使用 |
bg |
bg %1 |
将暂停的作业放入后台运行(需先Ctrl+Z暂停) | 让编译任务在后台继续 |
fg |
fg %1 |
将后台作业恢复到前台 | 重新交互式操作后台任务 |
nohup |
nohup ./long_task.sh & |
忽略挂起信号运行命令,输出重定向到nohup.out | 远程执行数据迁移任务 |
安全提示:优先使用
kill -15
(SIGTERM)而非kill -9
(SIGKILL),避免数据丢失。例如:kill -15 1234 # 尝试优雅终止 sleep 5 # 等待5秒 kill -9 1234 # 仅当进程无响应时强制终止
2.8 软件包管理命令
命令 | 示例 | 功能说明 | 典型场景 |
---|---|---|---|
apt |
sudo apt update && sudo apt upgrade |
更新软件包索引并升级系统(Debian/Ubuntu系) | 定期维护服务器安全 |
apt |
sudo apt install nginx |
安装软件包 | 部署Web服务器 |
yum |
sudo yum install httpd |
安装RPM包(RHEL/CentOS 7及以下) | 配置Apache服务 |
dnf |
sudo dnf install git |
现代RHEL/CentOS替代yum的命令(更高效依赖解析) | 安装开发工具链 |
rpm |
sudo rpm -ivh package.rpm |
安装RPM包(需手动处理依赖,-i 安装,-v 详细,-h 进度条) |
安装特定供应商软件 |
dpkg |
sudo dpkg -i package.deb |
安装DEB包(Debian系底层命令,-i 安装) |
修复损坏的Debian包 |
重要提示:不同发行版命令差异显著,操作前确认系统类型(
cat /etc/os-release
)。例如:# Ubuntu系统 sudo apt install docker.io # CentOS系统 sudo dnf install docker