进程间通信(IPC)详解:管道、消息队列、共享内存、Socket 与 Binder
进程默认拥有隔离地址空间,交换数据必须借助内核提供的 IPC。选择方式要看是否同机、消息边界、吞吐、延迟、持久性、安全与同步需求,没有一种机制在所有维度都最好。 匿名管道是单向字节流,常用于有亲缘关系进程;命名管道通过文件系统名称让无亲缘进程连接。消息队列保留消息边界,可异步解耦发送和接收,但有容量、复制和生命周期管理成本。共享内存把同一物理页映射进多个进程,数据交换少复制、吞吐高,却必须额外使用信号量、互斥量等协调读写。 Socket 提供统一的双向通信接口,Unix Domain Socket 适合同机,网络 Socket 可跨主机。它们是字节流或数据报语义,应用仍需定义协议、长度与错误恢复。信号适合传递少量事件,不宜承载复杂数据。Android Binder 则把调用、对象引用与身份校验结合到系统 IPC 模型中。 性能不能只数“拷贝次数”:上下文切换、序列化、锁竞争、缓存一致性和消息大小都重要。共享内存最快的说法只在正确同步且工作负载合适时成立。 误区是认为管道天然双向、TCP 一次发送对应一次接收、共享内存无需锁、消息队列必然持久,以及忽略对端崩溃与背压。小结:先定...
中断、异常与系统调用详解:从内核入口到缺页异常
中断、异常和系统调用都会让 CPU 转入内核处理程序,但来源不同。硬件中断通常异步发生,例如网卡收包或定时器到期;异常与当前指令同步,例如除零、非法指令和缺页;系统调用则是程序主动请求受保护服务。 入口大致经历:CPU 保存必要执行现场,根据向量找到处理程序,切换到内核权限和内核栈,内核判断原因并处理,最后恢复现场返回。具体架构会优化寄存器保存和入口指令,但权限检查与现场恢复不可省略。 缺页异常不一定是错误。若虚拟页合法但尚未映射,内核可分配物理页、从文件或 Swap 读取、更新页表,再重新执行触发指令;若地址非法,则向进程报告故障。系统调用如 read 还可能因数据未就绪把线程阻塞,调度其他任务。 中断处理应尽量短,把耗时工作延后执行,否则会增加系统响应延迟。系统调用也不是普通函数调用:它跨越保护边界,可能复制参数、检查权限并调度,因此频繁小调用可通过批量、缓冲等方式减少开销。 误区是把任何内核切换都叫上下文切换、认为缺页必然访问磁盘、把信号与硬件中断混同,以及在用户态直接执行特权操作。小结:区分触发来源、同步关系和处理结果,就能串起设备通知、内存按需分配与应用请求内核服务...
操作系统文件系统详解:inode、VFS、Page Cache 与日志机制
文件系统把持久化块设备组织成目录和文件。目录项建立名字到 inode 的映射,inode 保存类型、权限、大小、时间和数据块位置;文件名通常不在 inode 内,因此多个硬链接可指向同一 inode。符号链接则保存另一条路径。 应用打开路径时,内核逐级解析目录、检查权限并建立打开文件对象,再给进程一个文件描述符。描述符只是进程表中的索引;复制描述符可能共享文件偏移。VFS 提供统一接口,让不同具体文件系统实现 open、read、write 等操作。 读取通常先查 Page Cache,命中便免去设备 I/O;写入常先修改缓存页并标脏,内核稍后写回。write 返回不等于数据已落到稳定介质,关键数据需按语义调用 fsync,并注意目录项和文件内容可能需要分别持久化。顺序 I/O 往往比随机 I/O 更容易预读和合并。 日志文件系统先记录元数据或事务意图,再写最终位置,崩溃后通过日志恢复一致结构,但并不自动保证应用多文件事务。容量也不只受数据块限制,海量小文件可能先耗尽 inode。 误区是把删除文件等同立即释放空间(仍被进程打开时可能继续占用)、...
死锁详解:四个必要条件、Java 死锁排查与数据库死锁处理
死锁是多个执行单元永久等待彼此占有资源的状态。它同时需要四个条件:资源互斥;已持有资源时继续等待;资源不能被强制剥夺;等待关系形成环。破坏任一条件即可避免严格意义上的死锁。 最常用预防方式是建立全局锁顺序,所有线程都按同一顺序申请;也可一次性申请全部资源、使用可超时锁并失败回退、缩小临界区。银行家算法属于避免策略,通过判断分配后系统是否仍有安全序列决定是否批准,但需要预知最大需求,通用业务中较少直接使用。 检测可构建等待图:节点为线程或事务,边表示正在等待对方资源,图中出现环即有死锁候选。Java 可通过线程转储查看 BLOCKED 线程、持有锁与等待锁;数据库通常自动检测事务等待环,选择代价较小的事务回滚,应用必须正确重试整个事务。 死锁与饥饿、活锁不同。饥饿是长期得不到资源但系统仍前进;活锁是参与者不断响应却反复让步,没有有效进展。锁等待超时能恢复服务,却不代表根因已消失。 排查时记录锁名、获取顺序、持有时长和调用栈,并用一致顺序修复。误区是看到线程不动就断言死锁、在持锁时执行网络 I/O、重试单条 SQL 破坏事务语义,以及用更大的超时掩盖环。小结:设计阶段统...
CPU 调度与系统负载详解
CPU 调度从可运行任务中选择下一个执行者。目标常相互冲突:批处理关注吞吐和周转时间,交互任务关注响应,实时任务关注截止期,同时还要兼顾公平、优先级与多核局部性。 先来先服务简单但长任务会阻塞短任务;短作业优先能降低平均等待,却可能使长任务饥饿;时间片轮转给每个任务轮流运行,时间片太大会接近先来先服务,太小则上下文切换频繁。优先级调度需用老化等机制缓解饥饿。现代通用系统通常综合虚拟运行时间、优先级和负载均衡,而非只套一种教材算法。 上下文切换要保存寄存器、切换地址空间和恢复现场,还会影响缓存与 TLB,因此并非免费。CPU 密集任务适合接近核心数的并行度;大量 I/O 等待任务可有更多线程,但过多会增加调度与内存成本。 系统负载通常反映一段时间内可运行及某些不可中断等待任务数量,不等同 CPU 使用率。四核机器 load 为 4 可能刚好满载,单核则明显排队;高 load 配合低 CPU,可能是磁盘或不可中断 I/O 等待。判断时应结合运行队列、iowait、上下文切换和各核利用率。 误区是把负载值直接当百分比、认为线程越多吞吐越高、忽略任务亲和性和 NU...
Shell 编程基础知识总结
Shell 既是命令解释器,也是把程序组合成数据流的脚本语言。执行前会经历变量、命令替换、通配符和字段分割等展开,因此引用规则直接决定参数边界。除非明确需要分词,变量通常应写成 "$value"。 管道把前一进程的标准输出连接到后一进程的标准输入;重定向则把输入输出连接到文件或描述符。管道传递字节流,不自动保存记录结构。每个命令返回退出状态,0 通常表示成功,脚本应显式检查失败,而不是只看是否打印错误。 12345set -eufor file in "$@"; do [ -f "$file" ] || { echo "not a file: $file" >&2; exit 1; } process "$file"done 条件判断要区分字符串、整数与文件测试;循环遍历参数应使用 "$@" 保留每个参数边界。函数可复用逻辑,但复杂数据结构、并发控制和跨平台需求增长时,应考虑 Python 等更合适语言。临时文件需安全...
进程与线程详解:区别、状态、通信、上下文切换与虚拟线程
进程更接近资源与隔离边界:它拥有虚拟地址空间、打开文件、凭据等。线程是进程内的执行流,共享这些进程资源,但各自保留栈、寄存器和程序计数器。共享降低通信成本,也让竞态和故障影响更直接。 常见状态包括就绪、运行与阻塞。就绪线程具备运行条件只差 CPU;阻塞线程在等 I/O、锁或事件。时间片耗尽可从运行回到就绪,等待事件完成则从阻塞回到就绪。进程间交换数据需管道、共享内存、Socket 等 IPC,线程间可直接访问共享内存但必须同步。 上下文切换会保存旧线程现场、选择新线程并恢复,还可能扰动缓存和 TLB。进程切换通常涉及更强的地址空间隔离,但现代实现和同进程线程切换的实际差距不能只凭一句“进程重”判断。 Linux 的 fork 创建具有写时复制地址空间的子进程,exec 用新程序替换当前进程映像,wait 回收子进程退出状态。多线程程序在 fork 后子进程只保留调用线程,继承的锁状态可能危险,通常尽快 exec。 Java 虚拟线程由运行时调度到少量平台线程,适合大量阻塞型任务;它不会让 CPU 密集计算超过核心上限,也不能取消数据库连接等外部资源容量。误区是把并发...
操作系统专题:进程线程、内存管理、文件系统、I/O 多路复用、Linux 与 Shell
操作系统位于应用与硬件之间,向上提供进程、虚拟内存、文件和网络等抽象,向下管理 CPU、内存与设备。它的核心目标不是让资源无限,而是在有限硬件上实现共享、隔离、保护和可观察的性能。 学习可沿一条请求路径展开:程序通过系统调用进入内核;调度器让线程获得 CPU;虚拟地址经页表映射到物理页;缺页时可能触发分配或磁盘读取;文件系统把路径解析到 inode 和数据块;设备完成 I/O 后以中断通知;内核唤醒等待线程。这样可把零散名词连接起来。 进程是资源与隔离边界,线程是执行流;并发需要锁、信号量和条件变量,并警惕死锁。内存管理通过分页、TLB、页面置换和 Swap 在地址空间与物理内存间协调。文件系统负责命名、权限、缓存与崩溃一致性。I/O 多路复用让一个线程观察多个描述符,零拷贝减少数据搬运。 实践中可结合 Linux 工具理解指标:CPU 使用率不等于系统负载,内存“已用”包含可回收缓存,进程阻塞可能来自锁也可能来自 I/O。性能分析应先确定瓶颈资源,再追踪等待链。 误区是只背定义、不画用户态到内核态的流程,或把所有慢都归因于 CPU。小结:以资源...
操作系统常见面试题总结(上)
操作系统面试不应停在术语定义。用户态限制特权指令,应用通过系统调用请求内核;进程提供地址空间与资源隔离,线程共享进程资源并保存各自栈、寄存器和程序计数器。线程切换通常较轻,但仍有调度和缓存成本。 进程状态可概括为就绪、运行、阻塞等。就绪表示只等 CPU,阻塞表示等 I/O、锁或事件;事件完成后先回就绪队列,不会自动持续运行。调度器在响应、吞吐、公平和截止期之间取舍,时间片过短会增加切换,过长会降低交互响应。 并发带来竞态:结果依赖不可控执行顺序。临界区需要互斥,信号量可表达资源计数,条件变量让线程在谓词不满足时睡眠并在通知后重新检查。原子性、可见性和有序性是不同问题,单次原子读写不能自动保护复合操作。 死锁需互斥、持有并等待、不可剥夺和循环等待同时成立;统一锁顺序是常见预防方式。上下文切换也应准确表达:陷入内核不一定换线程,线程切换才需要保存并恢复不同执行上下文。 回答时最好给出机制、触发条件与代价。例如“线程更轻”要补充共享什么、切换省在哪里、何时锁竞争反而变慢。误区是把并发等同并行、把阻塞等同就绪、认为线程数越多越快。小结:围绕状态、资源边界和一次切换流程组织答...
Linux 基础知识总结
Linux 的重要观念是“许多资源可通过文件接口访问”。普通文件、目录、设备、管道和套接字虽语义不同,却可复用打开、读取、写入与关闭等接口。根目录下不同路径承担配置、运行数据、用户目录和虚拟内核信息等职责。 权限按所有者、组、其他用户分为读写执行;目录的读表示列出名字,执行表示穿越路径,不能照搬普通文件含义。进程有 PID、父子关系、凭据、环境和文件描述符。前台后台只是终端作业控制关系,守护进程则通常脱离交互终端长期运行。 排障应先形成指标链:用进程与线程视图定位 CPU 消耗,结合负载判断是否排队;查看内存、Swap 和页缓存;检查磁盘空间与 inode;观察网络监听、连接与丢包;最后通过日志和系统调用跟踪验证。命令输出是时刻快照,持续问题应采样趋势。 软件安装宜使用发行版包管理器,服务交给系统服务管理器,临时提权使用受控机制。日志轮转、文件描述符上限、时间同步和权限最小化都是线上基础工作。 误区是看到“used”内存高就清缓存、用 kill -9 作为默认停止方式、递归放宽到 777、只看磁盘块不看 inode,以及复制陌生命令直接执行。小结:Linux 基础不等于命令清...