3.如何保存CPU现场信息

本文探讨了操作系统如何在进程或线程切换时保存上下文信息,重点解析了i386体系结构下的线程切换代码。通过KiSwapContext函数调用SwapContext,保存旧线程信息,更新栈指针,并切换到新线程的内核栈。涉及到的内容包括寄存器、内核栈、地址空间、页表目录、TEB切换等。同时,文章提到了线程优先级的分配和调整机制,以及线程状态和运行时间的管理。
摘要由CSDN通过智能技术生成

3.讲完了进程和线程之后,我们的核心问题块来临了,操作系统到底是采用什么策略进行进程或线程调度的,也就是决定让哪个线程或者进程进入到CPU里面去执行。在讲这个问题之前我们还有一个很重要的上课讲的内容,进程或者线程切换的时候,我们如何保存其运行信息?

3.1线程的切换

我花费好几个小时去找这个的内容,因为我借的两本书上都没讲代码,而是直接给出了原理和答案,好在我还是找到了线程切换的一部分代码,但是我看了之后真的是发现好痛苦,不同的处理器体系结构代码是不同的,下面我以简单i386体系结构为例,来简单的描述一下操作系统是如何进程线程切换的,这里涉及到了很多的概念和内容,是需要对前面的内容进程拓展才能理解清楚的,相关方面的内容只能是自己去看书了。在WRK-v1.2\base\ntos\ke\amd64\Ctxswap.asm里面我们终于看到了代码:

includeksamd64.inc

......

;BOOLEAN

;KiSwapContext (

;    IN PKTHREAD OldThread,

;    IN PKTHREAD NewThread

;    )

       NESTED_ENTRY KiSwapContext, _TEXT$00

 

        GENERATE_EXCEPTION_FRAME        ; 生成异常页

        mov    rbx, gs:[PcCurrentPrcb] ; 获得当前PRCB地址

        mov    rdi, rcx                ; 旧线程地址换到rdi中

        mov    rsi, rdx                ; 新线程地址换到rsi总

        movzx  ecx, byte ptr ThWaitIrql[rdi] ; 禁止APC机制的中断影响

        call   SwapContext             ; //调用SwapContext

 

        RESTORE_EXCEPTION_STATE         ;

        ret                             ; 返回

 

        NESTED_END KiSwapContext, _TEXT$00

 

        subttl "Dispatch Interrupt"

/*这段程序是作为一个发生在 DISPATCH_LEVEL上的软中断的结果的输入,它的功能是处理DPC链表,当一个新的线程已经准备好到一个处理器上运行时,这个程序将进行新旧线程的上下文切换*/

DiFrame struct

        P1Home  dq ?                    ; PRCB地址段

        P2Home  dq ?                    ;

        P3Home  dq ?                    ;

        P4Home  dq ?                    ;

        SavedRbx dq ?                   ; 保存RBX

DiFrame ends

 

        NESTED_ENTRYKiDispatchInterrupt, _TEXT$00

 

        alloc_stack (sizeofDiFrame)    ; 进行堆的分配

        save_reg rbx, DiFrame.SavedRbx  ; 保存非易失性寄存器的内容

 

        END_PROLOGUE

 

        lea     rcx, (-128)[rbp]        ; 设置trap地址

        call    KiCheckForSListAddress  ; 检查SLIST地址

 

        mov     rbx, gs:[PcCurrentPrcb] ; 获得当前 PRCB地址

        and     byte ptr PbDpcInterruptRequested[rbx], 0;//清除请求

       KiDI10: cli       //上下文切换不能被中断,此处即禁止中断                      ;

        mov     eax, PbDpcQueueDepth[rbx] ; 获取DPC 队列深度        or      rax, PbTimerRequest[rbx] ; 合并计时器的值

 

ifndef NT_UP

 

        or      rax, PbDeferredReadyListHead[rbx] ; 合并延期准备表

endif

 

        jz      short KiDI20            ; if z, no DPCs to process

        mov     PbSavedRsp[rbx], rsp    ; save current stack pointer

        mov     rsp, PbDpcStack[rbx]    ; set DPC stack pointer

        mov     rcx, rbx                ; set PRCB address parameter

        call    KiRetireDpcList         ; process the DPC list

        mov     rsp, PbSavedRsp[rbx]    ; restore current stack pointer

 

KiDI20: sti                            ; enable interrupts

        cmp     byte ptr PbQuantumEnd[rbx], 0 ; check ifquantum end request

        je      short KiDI40            ; if e, quantum end not requested

        and     byte ptr PbQuantumEnd[rbx], 0 ; clearquantum end indicator

        call    KiQuantumEnd            ; process quantum end

 

KiDI30: mov     rbx,DiFrame.SavedRbx[rsp] ; restore nonvolatile register

        add     rsp, (sizeof DiFrame)   ; deallocate stack frame

        ret                             ; return

 

        mov     rbx, DiFrame.SavedRbx[rsp] ; restorenonvolatile register

        add     rsp, (sizeof DiFrame)   ; deallocate stack frame

        jmp     short KxDispatchInterrupt ;

 

        NESTED_ENDKiDispatchInterrupt, _TEXT$00

 

        NESTED_ENTRYKxDispatchInterrupt, _TE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值