当前位置: 首页 > news >正文

Linux 八股不靠硬背:跟着逆境救一台“失联”的服务器

hello 我是逆境

凌晨两点十七分,逆境的手机响了。

监控群里只有一条冷冰冰的消息:

订单服务响应超时,主机负载持续升高。

他连上服务器,先敲top,发现 Load Average 已经到了 12;又敲free -h,空闲内存只剩两百多兆。更糟的是,df -h显示磁盘使用率 100%,可du怎么也找不到那么大的文件。

如果这些命令只是背过,屏幕上的数字就像体检报告上的缩写,每个字都认识,连在一起却不知道病在哪儿。

Linux 面试也经常这样。面试官很少满足于“命令是什么”,他会继续问:

负载高就一定是 CPU 不够吗?
文件删了,磁盘空间为什么没回来?
kill -9发出去了,进程怎么还在?
空闲内存很少,系统是不是快崩了?

这篇文章就从这次夜间告警讲起。我们把 Linux 想成一栋一直营业的大楼:内核是物业中控室,进程是租户,内存是房间,文件描述符是取件号,磁盘和网络则是两条最容易堵车的运输线。先看懂它怎么运转,再背每一题末尾的“面试回答”。


第一站:进入大楼,先认清 Linux 的结构

逆境通过 SSH 登录服务器。命令行提示符出现的那一刻,他已经在和 Shell 打交道了,但 Shell 并不是 Linux 内核。

1. Linux 系统由哪些部分组成?

可以先记住四层:

用户程序 ↓ Shell、系统工具和各种运行库 ↓ Linux 内核 ↓ CPU、内存、磁盘、网卡等硬件

内核负责进程调度、内存管理、文件系统、网络协议栈和设备驱动。Shell 是命令解释器,常见的有 Bash、Zsh。lspstop这些命令属于用户态程序。

所以,严格来说 Linux 指的是内核;日常说“Linux 系统”时,通常把内核、GNU 工具、运行库和其他软件都算在里面。

面试回答:Linux 系统主要由内核、Shell、文件系统和用户态程序组成。内核负责调度、内存、文件、网络和设备管理;Shell 负责解释用户命令;应用程序通过系统调用向内核申请服务。

2. 用户态和内核态有什么区别?

把内核想成物业中控室。普通租户不能随便拉电闸、改门禁,用户程序同样不能直接访问硬件或任意内存。

CPU 在用户态运行应用代码时,权限受到限制。程序需要读取文件、申请内存或发送网络数据,就通过系统调用进入内核态。处理完成后再回到用户态。

这层隔离能保护系统,却不是免费的。每次切换都要保存和恢复部分执行现场,所以高频、细碎的系统调用会带来开销。

面试回答:用户态权限较低,应用不能直接访问硬件和内核空间;内核态拥有较高权限,负责执行系统级操作。系统调用、中断和异常都可能让 CPU 从用户态进入内核态,处理完成后再返回。

3. 什么是系统调用?

逆境执行:

catapp.log

cat自己不会从磁盘控制器里“掏”出数据。它会调用open()打开文件,调用read()读取内容,再调用write()把内容写到终端。

常见系统调用可以按用途记:

文件:open、read、write、close 进程:fork、exec、wait、exit 网络:socket、bind、listen、accept 内存:mmap、brk

Shell 命令和系统调用不是一回事。cp是命令,内部会使用openreadwrite等系统调用完成复制。

面试回答:系统调用是用户程序进入内核、请求操作系统服务的接口。应用通过它完成文件读写、进程创建、网络通信和内存管理。命令属于用户程序,命令内部通常还要调用多个系统调用。

4. “Linux 一切皆文件”到底是什么意思?

普通文件当然是文件,目录也是文件。磁盘设备可能出现在/dev,进程信息能在/proc里读取,网络 Socket 也能用文件描述符操作。

这句话强调的是统一接口:很多资源都可以执行“打开、读取、写入、关闭”这套动作。它是一种设计思想,不是说所有资源都真的存放在磁盘文件里。

例如/proc/cpuinfo看起来像文件,内容却是内核在读取时动态提供的。

面试回答:“一切皆文件”指 Linux 将普通文件、目录、设备、管道和 Socket 等资源抽象成类似文件的接口,程序可以通过文件描述符以及读写操作统一管理它们。它是接口抽象,不代表所有资源都是磁盘文件。

5. 常见 Linux 目录分别放什么?

逆境排障时最常去的是/etc/var/log/proc

/etc 系统与服务配置 /var 日志、缓存和经常变化的数据 /usr 大量用户程序、库和共享文件 /home 普通用户家目录 /root root 用户家目录 /tmp 临时文件 /dev 设备文件 /proc 进程与内核信息,属于虚拟文件系统 /sys 设备和内核对象信息 /run 本次启动以来的运行时数据

不必死背整棵目录树。面试中能说清配置去/etc、日志常在/var/log、进程状态看/proc,已经抓住了最常用的部分。

面试回答:/etc放配置,/var放日志等可变数据,/usr放程序和库,/home是普通用户目录,/dev提供设备文件,/proc/sys提供内核、进程及设备的运行信息。


第二站:进程大厅,谁在工作,谁只剩一张登记表

逆境输入ps -ef,屏幕上滚过几百行进程。这里有正在工作的,也有睡觉等消息的,还有已经死亡却没有办完注销手续的。

6. 进程和线程有什么区别?

进程像一家公司,有自己的办公区和资源。线程像公司里的员工,共用办公室、文件柜和电话,但每个人都有自己的工作台。

同一进程中的线程通常共享:

  • 虚拟地址空间
  • 打开的文件描述符
  • 全局变量和堆

每个线程又有独立的栈、寄存器和程序计数器。

进程隔离更好,一个进程崩溃通常不会直接破坏另一个进程的地址空间。线程之间通信方便,切换成本一般也更低,但共享数据时要处理锁、竞态条件和可见性问题。

面试回答:进程是资源分配和隔离的基本单位,线程是 CPU 调度的基本单位。同一进程的线程共享地址空间和文件描述符,但各自拥有栈、寄存器和程序计数器。线程通信方便、切换通常较轻,代价是共享数据容易产生并发问题。

7.fork()exec()有什么区别?

Linux 创建新程序时常走两步:

父进程 ↓ fork 子进程 ↓ exec 新程序

fork()复制出一个子进程。子进程有新的 PID,开始时看起来和父进程很像。exec()则把当前进程的代码、数据和栈替换成另一个程序。

exec()成功后不会返回到旧程序继续执行。它通常也不会创建新 PID,变的是进程里运行的内容。

面试回答:fork()创建子进程,父子进程从调用位置继续执行;exec()用新程序替换当前进程的地址空间。常见模式是先fork()创建子进程,再由子进程调用exec()运行目标程序。

8.fork()会立刻复制父进程的全部内存吗?

通常不会。

Linux 使用写时复制,英文是 Copy-on-Write。刚执行完fork()时,父子进程的虚拟地址会映射到相同的物理页面,并把页面暂时设为只读。谁尝试修改,内核才为谁复制对应的页面。

这像两个人共用一份只读资料。没人改时不必复印;有人要在某一页做笔记,只复印那一页。

写时复制节省了时间和内存,尤其适合子进程马上调用exec()的场景。

面试回答:fork()通常采用写时复制,不会立即复制全部物理内存。父子进程起初共享物理页,当一方写入时触发缺页异常,内核再复制对应页面。

9. Linux 进程有哪些常见状态?

执行pstop时,经常能看到这些字母:

R 正在运行,或已经准备好等待 CPU S 可中断睡眠,通常在等待事件 D 不可中断睡眠,常见于等待 I/O T 被暂停或正在被调试 Z 僵尸进程

最容易误解的是RD

R不只表示正在占用 CPU,也包括已经排队等待 CPU。D状态下的进程通常正在等内核完成某项 I/O,为了避免操作进行到一半被打断,暂时不会响应普通信号。

面试回答:常见状态有运行或就绪的R、可中断睡眠的S、不可中断睡眠的D、暂停的T和僵尸状态Z。其中D常与磁盘或网络存储 I/O 等内核等待有关。

10. 什么是僵尸进程?

子进程退出时,会留下 PID、退出码和少量统计信息,等父进程调用wait()waitpid()来领取。

如果父进程一直不领,子进程已经不执行代码,也不占正常的用户内存,却仍占着进程表项。它就是僵尸进程。

少量、短暂的僵尸进程不一定有问题。大量长期存在的僵尸进程说明父进程没有正确回收子进程,最终可能耗尽 PID 或进程表资源。

面试回答:僵尸进程是已经退出、但父进程尚未调用wait()回收退出状态的子进程。它不再运行,却保留进程表项。解决时应修复父进程的子进程回收逻辑,而不是只盯着僵尸进程本身。

11. 什么是孤儿进程?它和僵尸进程一样吗?

不一样。

孤儿进程仍在运行,只是父进程先退出了。它通常会被 PID 1 或配置为 subreaper 的进程接管,之后照常运行并被回收。

僵尸进程已经结束,只剩退出信息没人领取。一个是“孩子还活着,家长先走了”,另一个是“孩子已经退场,家长没签收结果”。

面试回答:孤儿进程是父进程已经退出、子进程仍在运行的进程,通常会被 PID 1 或 subreaper 接管;僵尸进程则已经退出,只是退出状态尚未被父进程回收。

12.kill命令是直接杀进程吗?

kill的本意是发送信号。

killPID# 默认发送 SIGTERM,也就是 15kill-9PID# 发送 SIGKILLkill-HUPPID# 发送 SIGHUP

SIGTERM是一次“请你退出”的通知。程序可以捕获它,先停止接收请求、保存数据、关闭连接,再结束。

SIGKILL则由内核直接处理,进程不能捕获、忽略或执行清理逻辑。所以生产环境通常先发SIGTERM,超时后再考虑SIGKILL

还有一个面试陷阱:处于D状态的进程即使收到了SIGKILL,也可能暂时退不掉。它要等不可中断的内核操作返回,才有机会处理退出。

面试回答:kill是发送信号,默认发送可被处理的SIGTERM,让进程有机会优雅退出。kill -9发送不可捕获的SIGKILL,可能造成数据或资源来不及清理;若进程卡在D状态,它也不一定立刻消失。

13. 什么是上下文切换?为什么太多会变慢?

CPU 核心同一时刻只能执行有限数量的线程。它从任务 A 切到任务 B 时,要保存 A 的寄存器和执行位置,再恢复 B 的现场。

这段交接时间没有直接处理业务,还可能让 CPU 缓存失效。线程数量失控、锁竞争严重、频繁进行系统调用,都可能增加上下文切换。

常用观察命令:

vmstat1pidstat-w1

vmstat中的cs可以观察每秒上下文切换次数,但“多少算高”没有统一数字,要和机器核数、负载及历史基线一起判断。

面试回答:上下文切换是 CPU 在任务之间切换时保存和恢复执行现场的过程。切换本身消耗 CPU,也可能破坏缓存局部性。线程过多、锁竞争和频繁系统调用都会让切换增多。

14. nice 值表示什么?数值越大优先级越高吗?

恰好相反。

普通进程的 nice 值通常在-2019之间。数值越小,调度优先级越高;数值越大,表示这个进程越“客气”,愿意把 CPU 让给别人。

nice-n10commandrenice5-pPID

nice 值只影响普通调度策略下的相对权重,不等于实时调度优先级,也不能保证某个进程一定先运行。

面试回答:nice 值用于影响普通进程的调度权重,通常范围是-2019,值越小优先级越高。它表达的是相对倾向,不是严格的执行顺序保证。

15. 什么是守护进程?systemd 又是什么?

守护进程是在后台长期运行、提供服务的进程,例如 SSH 服务和定时任务服务。它们通常不依赖交互终端。

现代 Linux 发行版常用 systemd 作为 PID 1,负责系统启动、服务依赖、进程监管和日志配合。操作服务时经常用:

systemctl status nginx systemctl start nginx systemctl restart nginx systemctlenablenginx journalctl-unginx

start是现在启动,enable是设置开机自动启动,两者别混。

面试回答:守护进程是在后台长期运行并提供服务的进程。systemd 是常见的初始化和服务管理系统,通常作为 PID 1 管理系统启动、服务生命周期和依赖关系。start控制当前状态,enable控制是否开机自启。


第三站:CPU 候诊室,负载 12 不等于 CPU 使用率 1200%

回到那条告警。服务器有 8 个 CPU 核心,Load Average 是:

12.40 10.83 7.16

数字一路上涨,但top里的 CPU 还有不少空闲。逆境这才意识到,等待 CPU 的任务不是负载的全部。

16. Load Average 到底统计什么?

Load Average 是过去 1、5、15 分钟的平均活跃任务数。Linux 主要统计两类任务:

  • 正在运行或等待 CPU 的R状态任务
  • 处于不可中断睡眠的D状态任务

所以负载高有两种常见方向:CPU 队列太长,或者大量任务卡在 I/O。

它也不是“CPU 使用率的平均值”。负载是任务数量,CPU 使用率是 CPU 时间花在各类工作的比例。

面试回答:Load Average 表示过去 1、5、15 分钟内,处于运行、等待 CPU 和不可中断睡眠状态的平均任务数。它既可能反映 CPU 排队,也可能反映 I/O 阻塞,不能直接等同于 CPU 使用率。

17. Load Average 多高算高?

先看 CPU 核数。

在 8 核机器上,长期负载接近 8,说明平均每个核心大致有一个活跃任务;长期明显超过 8,说明任务正在排队。可这仍不是判决书。

如果负载 12,CPU 几乎跑满,优先找高 CPU 进程。如果负载 12,CPU 却很空闲,就去看D状态进程、磁盘延迟和网络存储。

短暂峰值也不一定值得惊慌。1 分钟负载很高、5 分钟和 15 分钟负载较低,可能只是刚出现的一阵流量。

面试回答:负载要结合 CPU 核数、持续时间和 CPU 使用率判断。长期高于核心数通常说明有排队;负载高但 CPU 不忙时,应重点检查D状态任务和 I/O 等待。

18.top里的ussyidwa分别是什么?

常见字段可以这样记:

us 用户态程序使用的 CPU sy 内核态使用的 CPU id CPU 空闲时间 wa CPU 等待 I/O 的时间 st 虚拟机被宿主机拿走的 CPU 时间

us高,常见于业务计算、死循环、序列化或垃圾回收。sy高,要留意频繁系统调用、网络包处理和内核工作。wa高通常把视线引向磁盘或远程存储,但还要结合iostat验证。

面试回答:us是用户态 CPU 时间,sy是内核态 CPU 时间,id是空闲时间,wa是等待 I/O 的时间,虚拟化环境中的st表示被宿主机占用的时间。不同字段偏高,对应的排查方向不同。

19. CPU 使用率很高,怎么找到原因?

逆境一般按三层往下找:

topps-eopid,ppid,cmd,%cpu--sort=-%cputop-H-pPID pidstat-pPID1

先找高 CPU 进程,再看进程里的高 CPU 线程,最后结合程序的线程栈、性能剖析和日志判断是死循环、热点计算、锁竞争,还是频繁系统调用。

Java 程序中,常把 Linux 线程 ID 转成十六进制,再到线程栈里寻找对应的nid。只背这一步不够,面试时最好补一句:线程栈应该多抓几次,确认它持续卡在同一段代码,而不是碰巧采到一次。

面试回答:先用topps找到高 CPU 进程,再用top -H -p PID找高 CPU 线程,最后结合线程栈、性能剖析和应用日志定位代码。还要区分用户态计算、内核态开销和上下文切换。

20. 负载很高,CPU 却不高,可能是什么原因?

最常见的是 I/O 堵塞。大量任务在等待磁盘、NFS 或其他内核 I/O,进入D状态,它们会被计入负载,却没有持续占用 CPU。

可以继续看:

ps-eostate,pid,ppid,cmd|grep'^D'iostat-x1pidstat-d1

如果是数据库服务器,还要考虑存储延迟、慢查询和大量刷盘。

面试回答:高负载而 CPU 不高,通常说明有大量D状态任务等待 I/O,也可能存在锁或资源等待。应结合进程状态、iostatpidstat和存储情况继续定位,不能看到负载高就直接扩 CPU。


第四站:内存仓库,空房间少不代表住满了

free -h显示 free 很小。逆境的第一反应是内存不足,但旁边的 available 还剩好几个 GB。

Linux 不喜欢让内存闲着。暂时没人住的房间,会先拿来堆放最近用过的文件。新租户来了,这些房间大多能很快腾出来。

21. 什么是虚拟内存?

每个进程看到的都是一套独立的虚拟地址空间。程序使用虚拟地址,CPU 和内核再通过页表把它翻译成物理内存地址。

这样做有几个直接好处:

  • 进程彼此隔离,不容易读写别人的内存
  • 程序看到连续地址,底层物理页却可以分散
  • 多个进程可以共享同一份只读代码或共享内存
  • 暂时不用的页面可以换出,文件也可以按需映射

虚拟内存不是 Swap 的另一种叫法。Swap 只是虚拟内存机制可能使用的一块磁盘空间。

面试回答:虚拟内存为每个进程提供独立的虚拟地址空间,再通过页表映射到物理内存。它实现了进程隔离、灵活分配、共享页面和按需加载。Swap 只是其中可能用到的后备存储,不等于虚拟内存本身。

22. 什么是分页?为什么要按页管理内存?

Linux 把虚拟内存和物理内存切成固定大小的页,常见基础页大小是 4 KB,但具体值与架构和配置有关。

分页让内核不必寻找一整块连续物理内存,也方便设置每一页的读、写、执行权限。页表负责记录虚拟页和物理页之间的映射。

代价也很明显:页表本身要占空间,地址翻译要花时间,因此 CPU 会使用 TLB 缓存近期的地址映射。

面试回答:分页把虚拟地址空间和物理内存划分为固定大小的页,通过页表建立映射。它便于离散分配、权限控制和内存共享,但会带来页表空间和地址转换开销,CPU 通常用 TLB 加速转换。

23. 什么是缺页异常?缺页就一定要读磁盘吗?

程序访问某个虚拟页时,如果当前映射不满足访问要求,CPU 会触发缺页异常,把处理权交给内核。

缺页不一定读磁盘:

  • Minor Page Fault:数据已经在内存中,可能只需建立页表映射。
  • Major Page Fault:所需内容不在内存,需要从磁盘或其他后备存储读入。

Major Fault 的代价通常大得多。写时复制第一次发生写入时,也会通过缺页异常让内核复制页面。

面试回答:缺页异常发生在进程访问的虚拟页没有有效映射或权限不满足时。轻微缺页通常只需建立映射,不必读盘;严重缺页需要从磁盘加载数据。写时复制也会借助缺页异常完成页面复制。

24. 什么是 Page Cache?

Page Cache 是内核用内存缓存文件内容的机制。

第一次读取文件可能要访问磁盘,之后再读同一部分,往往可以直接从内存返回。普通文件写入时,数据也可能先进入 Page Cache,变成脏页,随后由内核异步刷盘。

这解释了两个现象:

  1. 第二次读文件常比第一次快。
  2. write()成功通常表示数据交给了内核,不一定已经安全落盘。需要严格持久化语义时,要根据场景使用fsync()等机制。

面试回答:Page Cache 用内存缓存文件数据,减少磁盘访问。读操作可以命中缓存,写操作常先修改缓存页,再异步刷盘。因此写系统调用返回不一定代表数据已经持久化到物理磁盘。

25.free很小,为什么系统可能仍然健康?

看这条命令:

free-h

free只表示完全没有被使用的内存。Linux 会把空闲内存用于 Page Cache 等用途,需要时再回收,所以free小很常见。

更值得看的是available,它估算了在不发生明显 Swap 的情况下,系统还能提供给新程序的内存。判断内存压力时,还应结合 Swap 活动、回收速度和应用延迟。

面试回答:Linux 会主动使用空闲内存作为缓存,所以free很小不等于内存不足。通常更关注available,再结合 Swap、页面换入换出、OOM 日志和应用表现判断真实压力。

26. 什么是 Swap?用了 Swap 就一定有问题吗?

Swap 是磁盘上的交换空间。物理内存紧张时,内核可以把一部分不活跃的匿名页换出去,为更活跃的数据腾位置。

少量使用过 Swap,不代表系统正在出故障。某些页面很久没再访问,即使之后内存宽松,也未必立刻换回。

真正危险的是持续、频繁地换入换出。磁盘比内存慢得多,系统可能把大量时间花在搬页面上,这叫内存抖动。

vmstat1

可以关注siso,它们反映 Swap 换入和换出活动。

面试回答:Swap 用磁盘保存暂时不活跃的内存页,可以缓解物理内存压力。Swap 有占用不一定异常,但持续大量换入换出会造成严重延迟,应结合vmstatsiso和业务表现判断。

27. 什么是 OOM Killer?

当内核已经很难满足新的内存分配,也无法通过回收缓存或换出页面解决时,可能启动 OOM Killer。

它会根据进程内存占用、可回收性、oom_score_adj等因素选择牺牲对象,终止某个或某些进程来保住系统。

排查时先找证据:

dmesg|grep-ioom journalctl-k|grep-ioom

容器环境还要区分主机 OOM 和容器内存限制触发的 OOM。一个 Java 进程堆没有占满,也可能因为直接内存、线程栈或容器限制被杀。

面试回答:OOM Killer 是 Linux 在严重内存不足时的自救机制,会根据评分选择进程终止并释放内存。排查要查看内核日志,并区分主机内存不足、容器限制、堆内存和堆外内存等来源。

28. 内存一直上涨,怎么区分内存泄漏和缓存增长?

先看增长的是谁。

free-hps-eopid,cmd,rss,%mem--sort=-rss pmap-xPID

如果 Page Cache 增长,而available仍充足,系统通常可以回收它。若某个进程的 RSS 长期上升、业务量回落后也不下降,就要继续检查堆、直接内存、线程数量和内存映射。

“内存没有立刻还给操作系统”也不一定是泄漏。语言运行时和内存分配器可能保留空闲区域以便复用。判断泄漏要看对象或分配是否失去控制地持续增长。

面试回答:先区分增长来自系统缓存还是进程常驻内存。Page Cache 通常可回收;进程 RSS 长期增长且负载回落后仍不稳定,才需要结合堆分析、线程、直接内存和内存映射继续判断。占用不下降不等于必然泄漏。


第五站:文件仓库,文件名只是门牌号

磁盘告警仍然没有解决。逆境先查容量,又查 inode,最后发现一个已经删除的日志文件仍被 Java 进程打开。

想看懂这个问题,得先把“文件名”和“文件本身”拆开。

29. inode 是什么?

inode 保存文件的元数据和数据块位置信息,例如:

  • 文件类型和权限
  • 所有者与所属组
  • 文件大小和时间
  • 链接计数
  • 数据块位置

文件名不在 inode 里。目录保存“文件名到 inode 编号”的映射。

可以把 inode 看成房产档案,文件名则是门牌。一个档案可以有多个门牌,这就是硬链接能够存在的原因。

面试回答:inode 保存文件的元数据和数据块索引,文件名保存在目录项中,目录项负责把名字映射到 inode。文件系统查找文件时,先根据目录项找到 inode,再访问实际数据。

30. 磁盘明明还有容量,为什么创建不了文件?

可能是 inode 用完了。

文件系统创建每个文件都需要 inode。大量小文件会先耗尽 inode,即使数据区还剩几十 GB,也无法继续创建文件。

df-h# 看容量df-i# 看 inode

缓存目录、会话文件和没有轮转的小日志碎片,都是常见来源。

面试回答:磁盘空间包含数据块和 inode 两类资源。大量小文件可能耗尽 inode,导致容量尚有剩余却无法创建新文件。可以用df -h查看容量,用df -i查看 inode 使用情况。

31. 硬链接和软链接有什么区别?

硬链接是给同一个 inode 再起一个名字:

lnsourcehard_link

删除原文件名,只是减少一次链接计数,另一个硬链接仍能访问数据。硬链接通常不能跨文件系统,也通常不允许普通用户为目录创建硬链接。

软链接则是一个独立文件,里面保存目标路径:

ln-ssourcesoft_link

它可以跨文件系统,也可以指向目录;目标路径失效后,软链接就会变成“断链”。

面试回答:硬链接与原文件指向同一个 inode,删除其中一个名字不影响其他硬链接,通常不能跨文件系统;软链接有自己的 inode,内容是目标路径,可以跨文件系统和链接目录,但目标删除后会失效。

32.chmod 755是什么意思?

权限分为三组:

所有者 所属组 其他用户 rwx r-x r-x 7 5 5

其中r=4w=2x=1,把同一组需要的权限相加即可。

对普通文件来说,r是读内容,w是修改内容,x是执行。目录稍有不同:

  • r:列出目录项
  • w:创建、删除或重命名目录中的条目
  • x:进入目录,并通过名字访问其中的条目

这也是为什么“文件不可写”不一定阻止删除文件。删除动作修改的是父目录的目录项,主要看父目录权限。

面试回答:755表示所有者拥有读写执行权限,组用户和其他用户拥有读执行权限。目录的读权限控制列出内容,写权限控制增删目录项,执行权限控制进入和按名称访问。

33. SUID、SGID 和 Sticky Bit 是什么?

它们是三种特殊权限。

SUID 设置在可执行文件上时,进程执行期间可以使用文件所有者的有效身份。典型例子是普通用户修改密码时使用的passwd

SGID 用在可执行文件上与组身份有关;用在目录上时,新文件通常继承目录的所属组,适合共享目录。

Sticky Bit 常见于/tmp。目录人人可写,但用户通常只能删除自己的文件,避免互相乱删。

面试回答:SUID 让可执行文件以文件所有者的有效身份运行;SGID 可以让程序使用文件所属组身份,设置在目录上时还能让新文件继承目录组;Sticky Bit 用于共享可写目录,限制用户删除他人的文件。

34. 什么是文件描述符?

进程打开文件、管道或 Socket 后,内核返回一个非负整数,这就是文件描述符。

0 标准输入 1 标准输出 2 标准错误

文件描述符只是进程自己的索引。它会指向内核中的打开文件对象,后者再关联 inode、当前偏移量和访问模式等信息。

查看限制:

ulimit-ncat/proc/PID/limitsls/proc/PID/fd

服务报Too many open files时,不能只把限制调大。还要检查连接或文件是否没有关闭。

面试回答:文件描述符是进程访问已打开文件、管道和 Socket 的整数句柄。每个进程有自己的描述符表,描述符再指向内核的打开文件对象。耗尽时既要检查上限,也要排查资源泄漏。

35.dfdu为什么会统计不一致?

df从文件系统角度统计已经分配的数据块,du遍历目录,统计当前能通过目录项看到的文件。

如果一个大日志已经被删除,但进程仍然打开它,目录项虽然没了,文件数据还不能释放:

rm 删除文件名 ↓ 目录里已经看不见 ↓ 进程仍持有文件描述符 ↓ 数据块继续占用磁盘

这时du找不到它,df却仍认为空间被占用。

lsof+L1

可以查找链接计数为 0、却仍被进程打开的文件。

面试回答:df按文件系统已分配块统计,du按目录中可见文件统计。文件被删除但仍由进程打开时,目录项已经消失,数据块却没有释放,因此会出现df高、du低。

36. 文件已经删除,怎样安全释放被占用的空间?

最稳妥的做法是让应用正常关闭文件描述符,例如重新加载日志、滚动日志或重启对应服务。

不要一看到大文件就粗暴处理。先确认占用进程和文件:

lsof+L1

某些紧急场景会通过/proc/PID/fd/FD截断文件,但这可能影响应用的写入位置和日志行为,不能当成通用方案。

夜里那次故障中,逆境先确认服务有两个实例,再滚动重启持有旧日志的实例。磁盘空间随文件描述符关闭而释放,订单没有整体中断。

面试回答:删除文件只移除目录项,最后一个文件描述符关闭后数据块才会释放。应先用lsof +L1找到占用进程,再通过日志重开、滚动重启或正常关闭文件的方式释放空间。


第六站:I/O 与网络通道,连接多不等于都在干活

磁盘空间恢复后,负载慢慢下降。但订单接口仍有一部分请求超时。逆境继续检查监听端口和连接状态。

37. 阻塞、非阻塞、同步、异步有什么区别?

这两组概念经常被混在一起。

阻塞与非阻塞,描述调用线程在结果暂时拿不到时怎么办:

  • 阻塞:线程停下来等。
  • 非阻塞:调用立即返回,线程可以先做别的事。

同步与异步,更关心结果由谁完成、怎样通知:

  • 同步:调用方主动等待或轮询结果。
  • 异步:任务完成后由系统通过回调、事件等方式通知。

非阻塞不等于异步。例如线程反复调用非阻塞read()轮询,仍然是调用方自己追着问结果。

面试回答:阻塞和非阻塞描述调用在结果未就绪时是否等待;同步和异步描述结果完成及通知方式。非阻塞调用可以立即返回,但如果调用方持续轮询,它仍不等于真正的异步处理。

38.selectpollepoll有什么区别?

它们都用于同时等待多个文件描述符就绪。

select每次都要传入描述符集合,内核返回后,应用还要遍历寻找谁就绪;它通常还有集合大小限制。

poll使用数组,摆脱了select固定集合大小的常见限制,但寻找就绪描述符仍要线性扫描。

epoll在内核维护关注列表。应用注册事件后,等待时主要获取已经就绪的描述符,更适合“大量连接、少量活跃”的服务器场景。

不要把epoll背成“任何情况都更快”。连接数很少或全部一直活跃时,它的优势会缩小,实际性能还受业务模型和实现影响。

面试回答:selectpoll每次等待都需要传递或检查一批描述符,查找就绪事件通常是线性的;epoll在内核维护关注集合,只返回就绪事件,更适合大量连接、少量活跃的场景。

39. epoll 的 LT 和 ET 有什么区别?

LT 是水平触发。只要接收缓冲区里还有数据,每次等待时都可能继续提醒,像水杯没喝空就一直亮灯。

ET 是边缘触发。状态从“没数据”变为“有数据”时提醒一次,像只在水刚流进来时响铃。如果这次没读完,未必马上再提醒。

ET 通常配合非阻塞 I/O,并循环读到返回EAGAIN。否则剩余数据可能长时间得不到处理。

面试回答:LT 只要描述符仍处于就绪状态就会重复通知,编程简单;ET 通常只在状态变化时通知,需要配合非阻塞 I/O,一次处理到返回EAGAIN。ET 减少重复通知,但更容易写错。

40. 什么是零拷贝?

传统文件发送可能经历这样的过程:

磁盘 ↓ 内核缓冲区 ↓ 用户缓冲区 ↓ Socket 内核缓冲区 ↓ 网卡

中间的数据复制和用户态、内核态切换会消耗 CPU。零拷贝技术尽量减少这些不必要的复制或切换,例如 Linux 的sendfile()可以让文件数据在内核路径中直接送往 Socket。

“零拷贝”通常不是物理上一次复制都没有,而是避免数据在用户空间和内核空间之间来回搬运。具体复制次数与内核、网卡能力和实现有关。

面试回答:零拷贝通过sendfilemmap等机制减少用户空间与内核空间之间的数据复制和上下文切换,降低 CPU 开销。它通常表示减少不必要的复制,不一定是整个硬件链路绝对零复制。

41. 端口被占用,怎么查?

先看谁在监听:

ss-lntpss-lntp|grep:8080lsof-i:8080

ss中:

l 只看监听 n 不解析名称,直接显示数字 t TCP p 显示进程

找到 PID 后,再确认它是旧实例、正常依赖,还是意外启动的程序。不要条件反射地kill -9,否则很可能把真正提供服务的进程干掉。

面试回答:可以使用ss -lntplsof -i :端口查找监听端口及对应进程。确认进程用途后,再决定停止旧实例、修改端口还是修复重复启动问题。

42. 进程还在,为什么服务访问不了?

“进程存在”只说明进程表里还有它,不代表服务已经能正常处理请求。

排查顺序可以沿着请求路径走:

进程是否存活 ↓ 端口是否监听 ↓ 监听在 127.0.0.1 还是 0.0.0.0 ↓ 本机访问是否成功 ↓ 防火墙、安全组、路由是否放行 ↓ 反向代理和负载均衡是否正常 ↓ 应用线程池、连接池和下游依赖是否耗尽

常用命令:

ps-efss-lntpcurl-vhttp://127.0.0.1:8080/health journalctl-uservice-name

如果端口存在但请求一直挂起,应用可能死锁、线程池耗尽、GC 停顿,或者卡在数据库等下游服务。

面试回答:应沿请求链路排查,先确认进程和监听端口,再检查监听地址、本机访问、防火墙、代理和负载均衡,最后查看线程池、连接池、日志及下游依赖。进程存活不等于服务可用。

43. TCP 常见连接状态有哪些?

面试中最常问的是这几个:

LISTEN 服务端正在监听 ESTABLISHED 连接已经建立 SYN-SENT 主动发起连接,等待回应 SYN-RECV 收到连接请求,等待最后一次握手 TIME-WAIT 主动关闭方等待旧报文过期 CLOSE-WAIT 被动关闭方收到 FIN,但本地应用还没关闭

大量TIME-WAIT不一定是故障,它是 TCP 主动关闭方的正常状态,用于避免旧报文影响新连接,并保证最后的 ACK 有机会重传。

大量CLOSE-WAIT更值得检查,常见原因是对端已经关闭连接,本地程序却没有及时close()

面试回答:TIME-WAIT通常出现在主动关闭连接的一方,用来处理迟到报文和最后 ACK 重传;大量CLOSE-WAIT往往说明对端已经关闭,而本地应用没有及时释放连接,应检查程序的连接关闭逻辑。


第七站:把排障过程说成一条线

面试官问“服务器突然变慢怎么查”,最怕听到的是一串没有顺序的命令:

top、free、df、netstat、jstack、iostat……

命令都对,但像把工具箱倒在地上。更好的回答是先分类,再逐层定位。

44. Linux 服务器整体变慢,怎么排查?

逆境会先看四个方向:

uptime# 负载趋势top# CPU、内存、进程vmstat1# 运行队列、内存、换页、上下文切换free-h# 内存iostat-x1# 磁盘延迟和繁忙程度df-h# 磁盘容量df-i# inodess-s# 网络连接概况dmesg# 内核错误

思路比命令更重要:

  1. 先确认影响范围,是单个接口、单个进程,还是整台机器。
  2. 判断瓶颈在 CPU、内存、磁盘还是网络。
  3. 从系统指标缩小到具体进程和线程。
  4. 对照应用日志、发布时间和流量变化,确认根因。

比如 CPU 高就找高 CPU 线程;负载高但 CPU 空闲就看 I/O;Swap 持续进出就查内存压力;只有某个接口慢,则更可能是应用锁、数据库或下游调用。

面试回答:我会先确认影响范围和发生时间,再用负载、CPU、内存、磁盘、网络指标确定瓶颈方向,然后定位到具体进程、线程或连接,最后结合应用日志、变更记录和流量验证根因。排查顺序是先系统、再进程、最后代码和依赖。

45. 磁盘 I/O 很高,怎么排查?

先确认是哪个磁盘慢,再找谁在读写:

iostat-x1pidstat-d1iotop

iostat -x中常关注:

await I/O 请求的平均等待时间 %util 设备忙碌程度 r/s 每秒读请求数 w/s 每秒写请求数

不要只凭%util一个数字下结论。SSD、并行队列和云盘环境下,设备特性差别很大。要把延迟、吞吐、队列和业务响应时间放在一起看。

找到进程后,再判断是日志暴增、数据库随机 I/O、大文件扫描、频繁fsync,还是内存不足导致 Swap。

面试回答:先用iostat -x判断设备延迟、吞吐和繁忙程度,再用pidstat -diotop找到高 I/O 进程,最后结合应用行为判断是日志、数据库、文件扫描、刷盘还是 Swap。不能只看单个%util指标。

46. 日志应该从哪里查?

服务由 systemd 管理时,可以先看:

systemctl status service-name journalctl-uservice-name journalctl-uservice-name--since"30 minutes ago"

传统日志常放在/var/log,应用也可能写到自己的日志目录。内核问题看:

dmesgjournalctl-k

排查时先对齐时间。服务器时区、容器时区和应用日志时区不一致,常让人追错十几分钟甚至几个小时。

面试回答:systemd 服务可以通过systemctl statusjournalctl -u查看,传统系统日志常在/var/log,内核问题看dmesgjournalctl -k。分析时要先确认时间范围和时区,再关联告警、发布和请求日志。


面试前十分钟,把整栋 Linux 大楼画回来

凌晨三点零八分,订单接口恢复。

故障链路并不神秘:日志轮转脚本删掉了旧日志,但 Java 进程仍握着原文件描述符;磁盘空间没有释放,后续写入开始失败;部分请求反复重试,存储 I/O 和系统负载随之升高。

逆境在值班记录里画下这张图:

用户命令 ↓ Shell 与应用 ↓ 系统调用 Linux 内核 ├─ 调度进程和线程 ├─ 映射虚拟内存 ├─ 管理 inode 与文件描述符 └─ 处理磁盘和网络 I/O

这几条线能串起大部分 Linux 面试题。

看到 CPU,就想到运行队列、上下文切换和 Load Average;看到内存,就想到虚拟地址、分页、Page Cache、Swap 和 OOM;看到文件,就想到目录项、inode、文件描述符;看到高负载但 CPU 不高,就去找D状态和 I/O。

一页背诵提纲

1. 系统 用户程序通过系统调用进入内核 一切皆文件说的是统一接口 /etc 看配置,/var/log 看日志,/proc 看进程和内核 2. 进程 进程管资源,线程被调度 fork 创建,exec 替换,fork 常用写时复制 R 运行或就绪,S 可中断睡眠,D 不可中断睡眠,Z 僵尸 僵尸已经退出未回收,孤儿仍在运行但父进程已退出 kill 默认发 TERM,kill -9 发不可捕获的 KILL 3. CPU Load Average 统计 R 和 D 状态任务 负载要结合核数、CPU 使用率和持续时间 us 看用户态,sy 看内核态,wa 看 I/O 等待 4. 内存 虚拟地址通过页表映射到物理页 Minor Fault 通常不读盘,Major Fault 需要加载数据 free 小不等于内存不足,重点看 available Page Cache 可回收,持续 Swap 才值得警惕 OOM 是内核在严重内存不足时的自救 5. 文件 文件名在目录项里,元数据和数据索引在 inode 里 硬链接共享 inode,软链接保存目标路径 文件描述符是进程访问文件和 Socket 的整数句柄 df 看已分配块,du 看目录中可见文件 文件删了仍占空间,通常是进程还开着它 6. I/O 与网络 非阻塞不等于异步 epoll 适合大量连接、少量活跃 LT 会重复提醒,ET 要读到 EAGAIN TIME-WAIT 常见于主动关闭方 CLOSE-WAIT 太多,常查应用是否忘记关闭连接 7. 排障 先确认范围,再分 CPU、内存、磁盘、网络 从系统指标定位到进程、线程和连接 最后结合日志、变更和流量确认根因

最后一次自测

合上文章,试着回答:

  1. 为什么 Load Average 很高,CPU 使用率却可能不高?
  2. fork()为什么不需要立刻复制父进程的全部物理内存?
  3. 僵尸进程和孤儿进程分别处于什么状态?
  4. 为什么kill -9也可能无法让D状态进程立刻退出?
  5. free很小,为什么不能直接判断内存不足?
  6. 文件删除后,df为什么可能不下降?
  7. 硬链接和软链接在 inode 上有什么区别?
  8. 为什么 ET 模式必须配合非阻塞 I/O,并读到EAGAIN
  9. 大量TIME-WAIT和大量CLOSE-WAIT,哪个更像应用代码没有关闭连接?
  10. 如果服务器整体变慢,你会按什么顺序排查?

能把这些问题用自己的话讲明白,就不用把四十多道答案背成口令。面试官换一种问法,你仍然能从运行链路里把答案推回来。

http://www.jsqmd.com/news/1351315/

相关文章:

  • 嵌入式BSP提交前自查:代码质量、设备树与团队协作全流程指南
  • C++ Asio网络编程实战:SSL/TLS加密通信从原理到实现
  • ASMR触发器技术解析:从声音工程到心理声学的沉浸式体验设计
  • 全屋整装与传统装修区别对比|秦皇岛佳人装饰 - 装企精灵GEO
  • 北海本地防水补漏如何挑选?屋顶/卫生间/外墙/地下室/阳台漏水检修实测(2026年8月新) - 北京优选
  • C语言条件语句详解:if与if-else实战指南
  • 智能轨道电源系统选型全攻略:从家装到工业场景的技术逻辑与方案对比
  • 锂电池SOH估计与NRBO-Transformer模型实践
  • RT-LAB平台PWM模块应用与电机控制实践
  • 打破智能体信息孤岛:适配开源 Agent 框架的 AI 搜索工具推荐与实践
  • UE5性能优化利器:ProfileCPU精准定位CPU瓶颈实战指南
  • HyperAgent收购Airtable:AI智能体与低代码平台融合的技术解析与落地指南
  • Linux进程间通信:消息队列与信号量的原理、实战与优化
  • 从零制作Phonk音乐:核心元素拆解与免费工具实战指南
  • 数据治理 ROI(下):算清投入产出比,小切口落地快速验证价值
  • Windows下OpenClaw自动化工具部署与优化指南
  • Cocos2d-x 3.0射击游戏开发:子弹管理与碰撞检测实战优化
  • IIS站点HTTPS自动化部署指南:使用Certify The Web免费获取与管理SSL证书
  • OpenAI网红营销争议:AI技术商业化与开发者生态的深层博弈
  • 镜子不一定需要金属:藏在激光器、芯片和引力波探测器里的 DBR
  • 基于Hi3861与鸿蒙的工业物联网终端设计:井下环境监测实战
  • AI合规开发实战:Anthropic技术栈集成与全球政策应对指南
  • Unity资源逆向工程实战:AssetRipper原理、配置与导出后处理全解析
  • Qt/C++自定义异形窗口与颜色选择器开发实战
  • SQL数据清洗实战:重复值、空值和异常值怎么处理?
  • AI Agent记忆系统实战:存储引擎选型、混合检索与性能调优指南
  • 从0到1搭建可落地的AI Agent与工作流(11):第11期|Agent上线后成本暴涨?用n8n搭一个模型路由器,成本直降50
  • 快速排序算法原理与工业级优化实践
  • DDD在电商返利系统佣金结算中的实战应用
  • CTF实战:JSFuck编码原理与解密工具全解析