ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入理解Linux内核--信号,中断,软中断,异常,性能优化

深入理解Linux内核--信号,中断,软中断,异常,性能优化 1.信号Signal信号是Linux内核向进程发送的异步通知机制用于告知进程发生了某个事件。1.1.信号的产生途径来源示例软件异常除零SIGFPE、非法内存访问SIGSEGV终端输入CtrlC→SIGINTCtrlZ→SIGTSTP软件条件定时器到期SIGALRM、管道断裂SIGPIPE系统调用kill()、raise()、tkill()1.2.信号的传递与处理流程产生信号 → 写入进程 task_struct 的 pending 位图 ↓ 信号递达Delivery内核在进程从内核态返回用户态时检查 pending ↓ 执行信号处理函数若注册了/默认动作终止/忽略/暂停/继续1.3.关键数据结构task_struct-signal指向共享的信号结构线程组共享task_struct-blocked信号屏蔽字sigpending挂起信号队列1.4.可靠信号 vs 不可靠信号不可靠信号1~31标准信号不排队可能丢失可靠信号32~64实时信号支持排队保证不丢失2.中断Interrupt中断是硬件或软件向CPU发出的异步事件通知迫使CPU暂停当前执行流转去执行中断处理程序。2.1.中断的分类中断 ├── 外部中断硬件中断 │ ├── 可屏蔽中断Maskable │ │ └── 通过 INTR 引脚触发受 IF 标志位控制 │ │ └── 例如网卡、磁盘、键盘、定时器PIT/HPET/APIC Timer │ └── 不可屏蔽中断NMI │ └── 通过 NMI 引脚触发不受 IF 位影响 │ └── 例如内存奇偶校验错误、严重硬件故障 │ └── 内部中断 ├── 异常Exception/同步中断—— 见下文 └── 软中断Softirq—— 见下文2.2.x86 架构中断描述符表IDTIDT包含256个条目0~2550~31Intel保留用于异常和NMI32~47通常分配给可屏蔽硬件中断IRQ0~IRQ151280x80传统系统调用入口int 0x80其他可由内核自定义分配2.3.中断处理流程Top Half1.CPU 收到中断请求2.保存现场寄存器、EFLAGS、返回地址压栈3.根据中断向量号查询 IDT找到中断处理程序4.执行do_IRQ()→ 调用注册的中断处理函数handler5.发送 EOIEnd of Interrupt给中断控制器6.恢复现场iret 返回2.4.中断控制器演进控制器特点8259A PIC传统可编程中断控制器级联支持 15 个 IRQIO-APIC多处理器时代支持中断分发到指定 CPUMSI/MSI-X消息信号中断PCIe 设备直接通过内存写触发无需专用中断线3.软中断Softirq / Bottom Half软中断是中断处理的后半部分机制用于将非紧急、耗时的工作从中断上下文硬中断推迟到软中断上下文执行。3.1.为什么需要 Bottom Half硬中断上下文Top Half要求快速执行因为中断是关闭的或优先级很高长时间执行会丢失其他中断Bottom Half 在开中断环境下运行可以被硬中断打断适合耗时操作3.2.Linux 的三种 Bottom Half 机制机制执行上下文特点使用场景Softirq中断上下文ksoftirqd静态分配最多 32 个同一类型可在多个 CPU 并行网络收发、块设备、定时器、SCSITasklet中断上下文基于 softirq 实现同一 tasklet 不会并行执行大多数驱动程序Workqueue进程上下文可以睡眠延迟较大需要睡眠的操作如 I/O、内存分配3.3.Softirq 的执行时机硬中断返回时如果当前pending的softirq存在直接执行ksoftirqd内核线程如果softirq过多避免用户态进程饿死由专门的内核线程处理显式调用如 local_bh_enable()、raise_softirq()3.4.预定义的 Softirq 类型enum{HI_SOFTIRQ0,// 高优先级 taskletTIMER_SOFTIRQ,// 定时器NET_TX_SOFTIRQ,// 网络发送NET_RX_SOFTIRQ,// 网络接收BLOCK_SOFTIRQ,// 块设备IRQ_POLL_SOFTIRQ,// 中断轮询TASKLET_SOFTIRQ,// 普通 taskletSCHED_SOFTIRQ,// 调度器HRTIMER_SOFTIRQ,// 高精度定时器RCU_SOFTIRQ,// RCUNR_SOFTIRQS};4.异常Exception异常是 CPU 在执行指令过程中同步检测到的错误或特殊条件与当前指令直接相关。4.1.异常的分类x86 架构类型名称特点示例Fault故障可纠正保存的 EIP 指向触发指令处理后可重新执行页错误Page Fault#PF、段不存在、除零错误Trap陷阱有意的同步事件保存的 EIP 指向下一条指令断点INT3、调试#DB、系统调用SYSCALLAbort中止严重错误无法精确定位通常终止进程双重故障Double Fault、机器检查Machine Check4.2.x86 常见异常向量向量号名称类型说明0#DEDivide ErrorFault除零或结果溢出1#DBDebugTrap/Fault调试异常3#BPBreakpointTrap断点int34#OFOverflowTrapinto指令溢出6#UDInvalid OpcodeFault无效操作码8#DFDouble FaultAbort处理异常时又发生异常13#GPGeneral ProtectionFault通用保护违规权限、段错误等14#PFPage FaultFault页错误缺页或权限不足18#MCMachine CheckAbort硬件错误由 CPU 报告4.3.页错误Page Fault详解页错误是 Linux 中最常见、最重要的异常触发 #PF 的情况 ├── 合法缺页Minor Fault │ ├── 匿名页首次访问 → 分配物理页并清零 │ ├── 文件映射页首次访问 → 从磁盘读取或共享零页 │ └── Copy-on-Write → 复制物理页 │ └── 非法访问Major Fault/SIGSEGV ├── 访问未映射地址 → 发送 SIGSEGV └── 权限不足写只读页等→ SIGSEGV4.3.1.Minor Fault与Major Fault维度Minor FaultMajor Fault是否需要磁盘 I/O❌ 否✅ 是耗时~1-10 μs~1-10 ms磁盘延迟主导是否阻塞进程极短几乎无感知显著阻塞常见原因首次访问、COW、栈增长磁盘读取、swap-in优化方向预分配、预触摸预读、加内存、锁内存、关 swap核心原则 Major Fault 是性能杀手Minor Fault 是正常开销。优化目标是消除 Major Fault控制 Minor Fault 的总量和频率。4.3.2.代码示例// 方法1mmap MAP_POPULATE预填充减少运行时缺页void*addrmmap(NULL,size,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE,-1,0);// 方法2madvise 顺序预读适合大文件顺序访问madvise(addr,size,MADV_SEQUENTIAL);madvise(addr,size,MADV_WILLNEED);// 提示内核预读// 方法3mlock 锁定关键内存防止 swap out但需谨慎使用mlock(addr,size);5.性能优化5.1.中断相关优化优化方向具体手段中断亲和性IRQ Affinity将中断绑定到特定 CPU避免缓存失效/proc/irq/n/smp_affinity中断合并Interrupt Coalescing网卡等硬件批量产生中断减少中断次数NAPINew API网络接收混合轮询中断高负载时关闭中断纯轮询MSI-X 多队列网卡多队列中断每个队列绑定不同 CPU实现并行处理硬中断轻量化Top Half 只做最少工作如禁用设备中断、标记状态其余放 Softirq/Workqueue5.2.Softirq 优化优化方向具体手段ksoftirqd 调优监控/proc/softirqs若某 CPU 的 ksoftirqd 占用过高考虑分散中断RPS/RFSReceive Packet Steering/Flow Steering软件层面将网络包处理分散到多个 CPU避免 Softirq 饥饿限制单次 softirq 处理数量防止用户态进程无法运行5.3.信号优化优化方向具体手段使用实时信号对可靠性要求高的场景使用SIGRTMIN~SIGRTMAX信号处理函数精简信号处理函数中只设置标志位主循环中处理逻辑类似 self-pipe tricksignalfd使用signalfd将信号转为文件描述符事件与 epoll 统一处理避免传统信号处理的竞态5.4.页错误优化优化方向具体手段减少 Major Fault预读madvise(MADV_SEQUENTIAL)、mlock锁定关键内存大页Hugepage使用 2MB/1GB 大页减少 TLB Miss 和页表遍历THPTransparent Hugepage内核自动合并小页为大页减少 Minor Fault预分配内存并触摸touch避免运行时缺页5.5.系统调用优化优化方向具体手段vDSO部分系统调用如gettimeofday通过用户态共享库直接执行避免陷入内核批量系统调用使用io_uring、readv/writev、sendmmsg减少上下文切换次数6.整体关系图用户进程 │ ├── 信号异步通知←──────────┐ │ │ │ │ 系统调用 ──→ 异常Trap │ │ 页错误Fault │ │ │ ↓ │ 内核态 ─────────────────────────┤ │ │ ├── 硬中断Top Half────────┤ │ 快速、关中断 │ │ ↓ │ ├── 软中断Bottom Half─────┘ │ 开中断、可延迟 │ ↓ └── 工作队列进程上下文 可睡眠
返回列表