Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >linux0.11中断处理源码初探

linux0.11中断处理源码初探

作者头像
theanarkh
发布于 2019-04-23 10:26:01
发布于 2019-04-23 10:26:01
1.8K00
代码可运行
举报
文章被收录于专栏:原创分享原创分享
运行总次数:0
代码可运行

系统初始化的时候,定义和初始化了中断向量表。并初始化8259的工作方式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 加载idt的基地址和限长到idt寄存器
lidt idt_descr
// 定义
idt_descr:
    .word 256*8-1       # idt contains 256 entries
    .long _id
// 初始化
_idt:    .fill 256,8,0

所以idt的内容是一个单位是8字节,长度是256的数组。linux0.11分为中断、系统、陷阱门。系统在启动的时候设置idt。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void trap_init(void)
{
    int i;

    set_trap_gate(0,&divide_error);
    set_trap_gate(1,&debug);
    set_trap_gate(2,&nmi);
    set_system_gate(3,&int3);   /* int3-5 can be called from all */
    set_system_gate(4,&overflow);
    set_system_gate(5,&bounds);
    set_trap_gate(6,&invalid_op);
    set_trap_gate(7,&device_not_available);
    set_trap_gate(8,&double_fault);
    set_trap_gate(9,&coprocessor_segment_overrun);
    set_trap_gate(10,&invalid_TSS);
    set_trap_gate(11,&segment_not_present);
    set_trap_gate(12,&stack_segment);
    set_trap_gate(13,&general_protection);
    // 缺页和写保护异常处理函数
    set_trap_gate(14,&page_fault);
    set_trap_gate(15,&reserved);
    set_trap_gate(16,&coprocessor_error);
    for (i=17;i<48;i++)
        set_trap_gate(i,&reserved);
    set_trap_gate(45,&irq13);
    // 允许8259接收中断
    outb_p(inb_p(0x21)&0xfb,0x21);
    outb(inb_p(0xA1)&0xdf,0xA1);
    set_trap_gate(39,&parallel_interrupt);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define _set_gate(gate_addr,type,dpl,addr) \
// 把dx即处理函数地址的低16位赋值给ax,不影响eax的高16位
__asm__ ("movw %%dx,%%ax\n\t" \
    /*
        设置idt描述符的第三个字节的内容,左移位数是字段对应的位置偏移,
        相加后赋值给dx,共16位,edx的高16位保存了处理函数的高16位地址
    */
    "movw %0,%%dx\n\t" \
    // 把eax即0x000080000 + 处理函数的地址赋值给idt描述符的前两个字节
    "movl %%eax,%1\n\t" \
    // 把edx的内容写入idt描述符的第5-8个字节
    "movl %%edx,%2" \
    : \
    : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
    // o表示使用内存地址并可以加偏移量
    "o" (*((char *) (gate_addr))), \
    // 指向保存选择子的首地址
    "o" (*(4+(char *) (gate_addr))), \
    // edx等于addr,eax等于0x00080000
    "d" ((char *) (addr)),"a" (0x00080000))

#define set_intr_gate(n,addr) \
    _set_gate(&idt[n],14,0,addr)

#define set_trap_gate(n,addr) \
    _set_gate(&idt[n],15,0,addr)

#define set_system_gate(n,addr) \
    _set_gate(&idt[n],15,3,addr)

其中idt描述符格式是,这个版本貌似还没有任务门。

在这里插入图片描述 还有一些是键盘,软盘等也设置中断。下面看一个异常处理程度。就是缺页或写保护异常的时候触发的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.globl _page_fault

_page_fault:
    // 交换两个寄存器的值,esp指向的位置保存了错误码
    xchgl %eax,(%esp)
    // 压栈寄存器
    pushl %ecx
    pushl %edx
    push %ds
    push %es
    push %fs
    // 内核数据段描述符
    movl $0x10,%edx
    mov %dx,%ds
    mov %dx,%es
    mov %dx,%fs
    // 如果是缺页异常,cr2保存了引起缺页的线性地址
    movl %cr2,%edx
    // 线性地址(有的话)和错误码入参
    pushl %edx
    pushl %eax
    // 1和eax与,结果放到ZF中
    testl $1,%eax
    // zf=0则跳转,即0是写异常,1是缺页异常
    jne 1f
    call _do_no_page
    jmp 2f
1:    call _do_wp_page
// 出栈,返回中断,会重新异常指令
2:    addl $8,%esp
    pop %fs
    pop %es
    pop %ds
    popl %edx
    popl %ecx
    popl %eax
    iret

缺页或写保护异常的时候,系统会把错误码和线性地址告诉处理程序。具体的处理可以见内存管理分析那篇文件。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
linux copy on write源码分析(基于linux0.11)
写时复制是有一块内存,由多个进程共享,属性是只读的,当有一个进程对这块内存进行写的时候,系统会先申请一块新的内存给他写。比如进程fork的时候,父子进程对应的物理地址都一样,这时候会在页表项中记录该物理地址是只读的,有一个进程写的时候,就会触发写保护异常。执行写时复制。
theanarkh
2019/09/05
2.3K0
Linux 内核0.11 系统调用详解(上)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/50608829
用户1147447
2019/05/26
1.8K0
linux缺页中断源码分析(基于linux0.11)
缺页中断发生在系统对虚拟地址转换成物理地址的过程中。如果对应的页目录或者页表项没有对应有效的物理内存,则会发生缺页中断。
theanarkh
2019/09/05
1.9K0
操作系统内核中的初始化工作
看完了进入内核前的工作后,我网络编程课的抄写作业自然是可以圆满完成啦,不过看了一部分后觉得确实很有意思,所以也是决定继续看下去,并且计划看完linux源码后跟着MIT6.s081写一个小的操作系统内核,希望我能够在6.29之前完成这个工作哈哈也就是我开始军训之前,补军训确实是个令人苦恼的事情。
ek1ng
2022/08/10
7750
操作系统内核中的初始化工作
fork系统调用过程分析
fork函数通过系统调用创建一个与原来进程几乎完全相同的进程,一个进程调用fork函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。
De4dCr0w
2019/02/27
2.1K0
linux0.11系统调用过程和fork源码解析
所以执行fork函数就会执行system_call函数,但是在这之前,还有些事情需要做,就是保存现场。下面是操作系统执行系统调用前,在内核栈里保存的寄存器,这个压入的寄存器和iret中断返回指令出栈的寄存器是对应的。其中ip指向的是调用系统调用返回后的下一句代码。
theanarkh
2019/04/24
1.5K0
linux0.11系统调用过程和fork源码解析
linux系统调用之read源码解析(基于linux0.11)
进程通过系统调用,从而进入中断处理,中断处理从系统调用表里找到sys_read函数执行。
theanarkh
2019/05/14
2.9K0
Linux内核20-Linux内核的异常处理过程
当异常发生时,Linux内核给造成异常的进程发送一个信号,告知其发生了异常。比如,如果一个进程尝试除零操作,CPU会产生除法错误异常,相应的异常处理程序发送SIGFPE信号给当前进程,然后由其采取必要的步骤,恢复还是中止(如果该信号没有对应的处理程序,则中止)。
Tupelo
2022/08/15
1.7K0
【linux学习指南】linux捕捉信号
如果信号的处理动作是⽤⼾⾃定义函数,在信号递达时就调⽤这个函数,这称为捕捉信号。 由于信号处理函数的代码是在⽤⼾空间的,处理过程⽐较复杂,举例如下:
学习起来吧
2024/12/01
1180
【linux学习指南】linux捕捉信号
Linux内核19-中断描述符表IDT的初始化
至此,我们已经理解了X86架构如何在硬件层面如何处理中断和异常,那么接下来,我们看看Linux内核管理这些中断和异常。
Tupelo
2022/08/15
9730
系统调用(int 0x80)详解
在系统启动时,会在sched_init(void)函数中调用set_system_gate(0x80,&system_call),设置中断向量号0x80的中断描述符:
全栈程序员站长
2022/09/30
1.6K0
【linux学习指南】linux捕捉信号(二)软中断&&缺⻚中断?等&& 如何理解内核态和⽤⼾态
如果是这样,操作系统不就可以躺平了吗?对,操作系统⾃⼰不做任何事情,需要什么功能,就向中 断向量表⾥⾯添加⽅法即可.操作系统的本质:就是⼀个死循环!
学习起来吧
2024/12/30
1340
【linux学习指南】linux捕捉信号(二)软中断&&缺⻚中断?等&& 如何理解内核态和⽤⼾态
操作系统内存换入-请求调页---14
虚拟内存是实现分段和分页的关键所在,而分段和分页是操作系统管理内存的两个核心机制。
大忽悠爱学习
2022/08/23
6940
操作系统内存换入-请求调页---14
进入Linux内核前的准备
最近看到这个github仓库flash-linux0.11-talk,觉得还算是蛮有意思的,加上网络编程的课程又有抄写一段tcp协议实现代码或者交一篇linux内核源码阅读的笔记,还是比较讨厌这种低效率的抄写的所以就想写篇文章记录一下粗浅阅读源码后的大概了解,这个github仓库作者的文章我觉得写的还是不错的对于我这类小白而言,也比较有看得下去的动力。
ek1ng
2022/08/10
5.8K0
进入Linux内核前的准备
xv6(5) 中断代码部分
公众号后台回复 $interrupt$ 可获取原图,另外我说明一下我画的流程图啊,的确是不标准的,有很多环了,我有试过只画一根线比如说 $iret$ 出去一根线后,按理说不会回到 $iret$ 而是直接指向原任务那个块。但是因为整个流程图的元素太多,这样画很难看很难看,所以我没采用。虽然如上图那么画不是那么准确,但是意思表达应该还是很明确的,而且相对来说好看些。诸位有什么好的建议还请指出,谢谢。不多说废话了,来看 $xv6$ 的中断机制
rand_cs
2023/12/05
3760
通过linux0.11源码理解进程的虚拟地址、线性地址、物理地址
进程的地址有三种,分别是虚拟地址(逻辑地址)、线性地址、物理地址。在分析之前先讲一下进程执行的时候,地址的解析过程。在保护模式下,段寄存器保存的是段选择子,当进程被系统选中执行时,会把tss和ldt等信息加载到寄存器中,tss是保存进程上下文的,ldt是保存进程代码和数据段的首地址偏移以及权限等信息的。假设当前执行cs:ip指向的代码,系统根据ldt的值从gdt中选择一个元素,里面保存的是idt结构的首地址。然后根据cs的值选择idt表格中的一项,从而得到代码段的基地址和限长,用基地址加上ip指向的偏移得到一个线性地址,这个线性地址分为三个部分,分别是页目录索引,页表索引,物理地址偏移。然后到页目录吧和页表中找到物理地址基地址,再加线性地址中的偏移部分,得到物理地址。下面我们看看这些内容是怎么设置的,使得执行的时候能正确找到我们想要的地址去执行代码。我们从fork函数开始。到进程被调度执行时所发生的事情。fork函数的具体调用过程之前已经分析过。下面贴一下主要的代码。
theanarkh
2019/04/24
1.5K0
通过linux0.11源码理解进程的虚拟地址、线性地址、物理地址
Linux内核21-Linux内核的中断处理过程
如前所述,我们知道异常的处理还是比较简单的,就是给相关的进程发送信号,而且不存在进程调度的问题,所以内核很快就处理完了异常。
Tupelo
2022/08/15
2.6K0
Linux内核21-Linux内核的中断处理过程
Linux中断一网打尽(1) —— 中断及其初始化
既然叫中断, 那我们首先就会想到这个中断是中断谁?想一想计算机最核心的部分是什么?没错, CPU, 计算机上绝大部分的计算都在CPU中完成,因此这个中断也就是中断CPU当前的运行,让CPU转而先处理这个引起中断的事件,通常来说这个中断的事件比较紧急,处理完毕后再继续执行之前被中断的task。比如,我们敲击键盘,CPU就必须立即响应这个操作,不然我们打字就全变成了慢动作~。说白了中断其实就是一种主动通知机制,如果中断源不主动通知,那想知道其发生了什么事情,只能一次次地轮询了,白白耗费CPU。
扫帚的影子
2020/02/25
1.7K0
Linux中断一网打尽(1) —— 中断及其初始化
linux信号处理源码分析(基于linux0.11)
linux的信号处理时机在系统调用结束后。这里以fork系统调用函数为例子讲解这个过程。下面是fork函数的定义。
theanarkh
2019/09/02
4.7K2
linux信号处理源码分析(基于linux0.11)
ucoreOS_lab1 实验报告
进入 /home/moocos/ucore_lab/labcodes_answer/lab1_result 目录下
Angel_Kitty
2019/07/15
1.7K0
ucoreOS_lab1 实验报告
相关推荐
linux copy on write源码分析(基于linux0.11)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验