Kernel Exploring
  • 前言
  • 支持
  • 老司机带你探索内核编译系统
    • 编译出你的第一个内核
    • 内核编译中的小目标
    • 可能是kbuild中最直接的小目标 – help
    • 使用了一个kbuild函数的目标 – cscope
    • 内核中单个.o文件的编译过程
    • 根目录vmlinux的编译过程
    • 启动镜像bzImage的前世今生
    • setup.bin的诞生记
    • 真假vmlinux–由vmlinux.bin揭开的秘密
    • bzImage的全貌
    • kbuild系统浅析
  • 启动时的小秘密
    • INIT_CALLS的秘密
    • 内核参数
  • 内核加载全流程
    • bootloader如何加载bzImage
    • 内核压缩与解压
    • 内核加载的几个阶段
    • 保护模式内核代码赏析
  • 内存管理
    • 内核页表成长记
      • 未解压时的内核页表
      • 内核早期的页表
      • cleanup_highmap之后的页表
      • 映射完整物理地址
      • 启用init_level4_pgt
    • 自底而上话内存
      • e820从硬件获取内存分布
      • 原始内存分配器--memblock
      • 页分配器
        • 寻找页结构体的位置
        • 眼花的页结构体
        • Node-Zone-Page
        • 传说的伙伴系统
        • Compound Page
        • GFP的功效
        • 页分配器的用户们
      • slub分配器
        • slub的理念
        • 图解slub
      • 内存管理的不同粒度
      • 挑战和进化
        • 扩展性的设计和实现
        • 减少竞争 per_cpu_pageset
        • 海量内存
        • 延迟初始化
        • 内存热插拔
        • 连续内存分配器
    • 虚拟内存空间
      • 页表和缺页中断
      • 虚拟地址空间的管家--vma
      • 匿名反向映射的前世今生
      • 图解匿名反向映射
      • THP和mapcount之间的恩恩怨怨
      • 透明大页的玄机
      • NUMA策略
      • numa balance
      • 老版vma
    • 内存的回收再利用
      • 水线
      • Big Picture
      • 手动触发回收
      • Page Fram Reclaim Algorithm
      • swapfile原理使用和演进
    • 内存隔离
      • memcg初始化
      • 限制memcg大小
      • 对memcg记账
    • 通用
      • 常用全局变量
      • 常用转换
    • 测试
      • 功能测试
      • 性能测试
  • 中断和异常
    • 从IDT开始
    • 中断?异常?有什么区别
    • 系统调用的实现
    • 异常向量表的设置
    • 中断向量和中断函数
    • APIC
    • 时钟中断
    • 软中断
    • 中断、软中断、抢占和多处理器
  • 设备模型
    • 总线
    • 驱动
    • 设备
    • 绑定
  • nvdimm初探
    • 使用手册
    • 上帝视角
    • nvdimm_bus
    • nvdimm
    • nd_region
    • nd_namespace_X
    • nd_dax
      • dev_dax
  • KVM
    • 内存虚拟化
      • Qemu内存模型
      • KVM内存管理
  • cgroup
    • 使用cgroup控制进程cpu和内存
    • cgroup文件系统
    • cgroup层次结构
    • cgroup和进程的关联
    • cgroup数据统计
  • 同步机制
    • 内存屏障
    • RCU
  • Trace/Profie/Debug
    • ftrace的使用
    • 探秘ftrace
    • 内核热补丁的黑科技
    • eBPF初探
    • TraceEvent
    • Drgn
  • 内核中的数据结构
    • 双链表
    • 优先级队列
    • 哈希表
    • xarray
    • B树
    • Maple Tree
    • Interval Tree
  • Tools
  • Good To Read
    • 内核自带文档
    • 内存相关
    • 下载社区邮件
Powered by GitBook
On this page
  • 雷锋和雷峰塔
  • 处理不同
  • 对应的中断向量

Was this helpful?

  1. 中断和异常

中断?异常?有什么区别

在学习的初期,我一直有这么个疑惑:

不都是在IDT中么?不都是通过vector number索引么?中断和异常到底有啥区别呢?

这次我们就来尝试揭开这个谜团。

雷锋和雷峰塔

在想究竟用哪个标题来描述这两者之间的区别,突然想到之前看到过这个就用上了。

当然,实际上这两者的差别并没有这么大。我能想到的两点区别是:

  • 来源不同

  • 处理不同

  • 位置不同

来源不同是指中断是外界引入的。比如键盘,硬盘,网络的数据相应是中断,而异常则是软件执行时自己触发的,比如除0,溢出。 在处理上,异常通常是发送一个信号给到执行的进程,由进程自行决定该如何处理。而中断的处理则由中断函数在处理。 位置不同写的有点模糊,意思是在IDT中,异常和nmi中断的中断向量是固定的,而可屏蔽中断的中断向量是写死的。

来源的不同就不用我来讲了,这是个事实。我就简单说一下后两者。

处理不同

总的来说,中断和异常的处理在内核中是分成两套机制完成的。

  • 异常的处理最后落到给进程发送信号上

  • 中断的处理最后落到do_IRQ函数上

具体的细节将在后续的小节中展开。

对应的中断向量

除此之外,中断和异常在IDT中的位置也是有讲究的。

  • 异常和nmi的中断向量是固定的

  • 可屏蔽中断的中断向量则是可配的

在上一节中,我们看到了中断向量的整个布局。现在我们进一步仔细看看其中哪些是中断哪些是异常。 下面的描述在文件arch/x86/include/asm/irq_vectors.h中。

*  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
*  Vectors  32 ... 127 : device interrupts
*  Vector  128         : legacy int80 syscall interface
*  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
*  Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts

可以看到其中大部分是中断,而在0-31中保存的是异常的中断向量。那进一步再来看异常向量的布局。

/* Interrupts/Exceptions */
enum {
	X86_TRAP_DE = 0,	/*  0, Divide-by-zero */
	X86_TRAP_DB,		/*  1, Debug */
	X86_TRAP_NMI,		/*  2, Non-maskable Interrupt */
	X86_TRAP_BP,		/*  3, Breakpoint */
	X86_TRAP_OF,		/*  4, Overflow */
	X86_TRAP_BR,		/*  5, Bound Range Exceeded */
	X86_TRAP_UD,		/*  6, Invalid Opcode */
	X86_TRAP_NM,		/*  7, Device Not Available */
	X86_TRAP_DF,		/*  8, Double Fault */
	X86_TRAP_OLD_MF,	/*  9, Coprocessor Segment Overrun */
	X86_TRAP_TS,		/* 10, Invalid TSS */
	X86_TRAP_NP,		/* 11, Segment Not Present */
	X86_TRAP_SS,		/* 12, Stack Segment Fault */
	X86_TRAP_GP,		/* 13, General Protection Fault */
	X86_TRAP_PF,		/* 14, Page Fault */
	X86_TRAP_SPURIOUS,	/* 15, Spurious Interrupt */
	X86_TRAP_MF,		/* 16, x87 Floating-Point Exception */
	X86_TRAP_AC,		/* 17, Alignment Check */
	X86_TRAP_MC,		/* 18, Machine Check */
	X86_TRAP_XF,		/* 19, SIMD Floating-Point Exception */
	X86_TRAP_IRET = 32,	/* 32, IRET Exception */
};

这个表大家也可以对应SDM Volume 3中Table 6-1 Protected-Mode Exceptions and Interrupts一起看。这样也找到了手册和代码之间的一个对应关系。

好了,了解了这两者的区别后,我们就可以来看看内核中是如何处理他们的了。

Previous从IDT开始Next系统调用的实现

Last updated 3 years ago

Was this helpful?