Windows进程&线程
+ -

Windows内核线程切换

2023-11-14 2 0

线程切换的函数是:KiSwapThread,该函数内部调用 KiSwapContext进行堆栈信息的切换。
ReactOS的源代码如下:

LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread,
IN PKPRCB     Prcb 
)    
{
    BOOLEAN ApcState = FALSE;
    KIRQL WaitIrql;
    LONG_PTR WaitStatus;
    PKTHREAD NextThread;
    ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);

    /* Acquire the PRCB lock */
    KiAcquirePrcbLock(Prcb);

    /* Get the next thread */
    NextThread = Prcb->NextThread;
    if (NextThread)
    {
        /* Already got a thread, set it up */
        Prcb->NextThread = NULL;
        Prcb->CurrentThread = NextThread;
        NextThread->State = Running;
    }
    else
    {
        /* Try to find a ready thread */
        NextThread = KiSelectReadyThread(0, Prcb);
        if (NextThread)
        {
            /* Switch to it */
            Prcb->CurrentThread = NextThread;
            NextThread->State = Running;
        }
        else
        {
            /* Set the idle summary */
            InterlockedOrSetMember(&KiIdleSummary, Prcb->SetMember);

            /* Schedule the idle thread */
            NextThread = Prcb->IdleThread;
            Prcb->CurrentThread = NextThread;
            NextThread->State = Running;
        }
    }

    /* Sanity check and release the PRCB */
    ASSERT(CurrentThread != Prcb->IdleThread);
    KiReleasePrcbLock(Prcb);

    /* Save the wait IRQL */
    WaitIrql = CurrentThread->WaitIrql;

    /* Swap contexts */
    ApcState = KiSwapContext(WaitIrql, CurrentThread);

    /* Get the wait status */
    WaitStatus = CurrentThread->WaitStatus;

    /* Check if we need to deliver APCs */
    if (ApcState)
    {
        /* Lower to APC_LEVEL */
        KeLowerIrql(APC_LEVEL);

        /* Deliver APCs */
        KiDeliverApc(KernelMode, NULL, NULL);
        ASSERT(WaitIrql == 0);
    }

    /* Lower IRQL back to what it was and return the wait status */
    KeLowerIrql(WaitIrql);
    return WaitStatus;
}

内核中调用KiSwapThread函数的有:

  • KeDelayExectureinThread
  • KeWaitForSingleObject ,调用该函数的太多
  • KeWaitForSingleObjects
  • KeTerminateThread
  • NtYieldExecution
  • KiAttachProcess

线程切换时:

  • 应先切换堆栈信息
  • 然后通过RET可以切换RIP

线程切换总结:

  • Windows中大部分API调用了SwapContext函数,也就是说,当线程调用了API,就是导致线程切换
  • 线程切换时会比较是否属于同一进程,如果不是,切换CR3,CR3换了,进程也就换了。

如果一个程序不调用API,也会出现线程切换的。这是因为中断、异常会导致线程切换。

时钟中断切换导致线程切换

时钟中断函数
{
    HalBeginSystemInterrupt
    ...
    HalEdnSystemInterrupt
    {
        KiDispatchInterrupt
        {
            SwapContext
        }
    }
}

线程切换的几种情况:

  • 主动调用API函数
  • 异常处理
  • 时钟中断

    时钟中断会导致线程进行切换,但并不是说只要有时钟中断就一定会切换线程,时钟中断时,两种情况会导致线程切换:
    1、当前的线程CPU时间片到期
    2、有备用线程(KPCR.PrcbData.NextThread)

如果一个线程不调用API,在代码中断屏蔽中断(CLI指令),并且不会出现异常,那么当前线程永久占用CPU,单核占用率1005,2个核就是50%。

0 篇笔记 写笔记

Windows内核线程睡眠
许多读者一定使用过Sleep函数。这能使程序停下一段时间。许多需要连续、长期执行,但是又不希望占太多CPU使用率的任务,可以在中间加入睡眠。这样能使CPU使用率大大降低。即使睡眠的时间非常短(几十个毫秒)。在驱动中也可以睡眠。使用到的内核函数的原型如下: NTSTATUS Ke......
Windows内核驱动创建线程
有时候需要使用线程来完成一个或者一组任务。这些任务可能耗时过长,而开发者又不想让当前系统停止下来等待。在驱动中停止等待很容易使整个系统陷入“停顿”,最后可能只能重启电脑。但一个单独的线程长期等待,还不至于对系统造成致命的影响。另一些任务是希望长期、不断的执行,比如不断写入日志。为此启动一个特殊的线程......
Windows驱动线程创建与退出
在应用层时,我们可以使用CreateThread来创建一个线程,这时如果创建成功,会退回一个线程句柄。而当创建的这个线程退出时,这个线程变为激活态,即我们可以通过WatiForSingleObject返回WAIT_OBJECT_0.如:HANDLE hThread = CreateThread(......
CreateThreadpoolWork线程
PTP_WORK WINAPI CreateThreadpoolWork( __in PTP_WORK_CALLBACK pfnwk, __in_out_opt PVOID pv, __in_opt PTP_CALLBACK_ENVIRON pcbe);......
Windows内核线程休眠KeSleep函数
//传入的数据若为1000,则 睡眠的时间为: 1000 * 100 ns * 10 *1000 =1sVOID KeSleep(LONG msec){ #define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLI......
SavedApcState与线程挂靠
_KTHREAD线程0x258地址处: +0x258 SavedApcState : _KAPC_STATE +0x258 SavedApcStateFill : [43] UChar此为备份SavedApcState,用于当线程挂靠到别的进程时,保存当前进程的APC State......
PsExitSpecialApc线程的退出示例
在上一节KiInsertQueueApc中,可以看到有一个特殊的APC,其为PsExitSpecialApc,表示线程退出的APC. if (Apc->NormalRoutine) { /* Normal APC; is it the Thread Termin......
窗口与线程的关系
一个GUID线程,会对应一个消息队列。该队列就在THREADINFO结构体中的MessageQueue中。消息的产生与发送SP++会在GetMessage中挂一个钩子,所以会收到消息。键盘 / 鼠标SendMessage/PostMessage系统产生在Win32k.sys中有2个线程Ini......
线程ETHREAD
每个线程在内核都有一个对应的结构体:ETHREAD,ETHREAD的第一个成员为KTHREAD.1: kd> dt _ETHREADnt!_ETHREAD +0x000 Tcb : _KTHREAD +0x5e0 CreateTime : ......
线程等待链表/调度链表
线程3种状态:正在运行就绪等待等待线程链表阻塞的线程在等待线程链表中。KTHREAD结构体中: +0x0d8 WaitListEntry : _LIST_ENTRY +0x0d8 SwapListEntry : _SINGLE_LIST_ENTRY当一个线程处于等待状......
模拟线程切换ThreadSwitch源代码(X86)
ThreadSwitch.cpp// ThreadSwitch.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "ThreadCor......
Windows内核进程&线程函数大全
1. PEPROCESS NTAPI PsGetCurrentProcess2. HANDLE NTAPI PsGetCurrentProcessId(VOID) 3. variable PsGetCurrentThreadId4. define PsGetCur......
Windows内核线程切换
线程切换的函数是:KiSwapThread,该函数内部调用 KiSwapContext进行堆栈信息的切换。ReactOS的源代码如下:LONG_PTR FASTCALL KiSwapThread(IN PKTHREAD Thread,IN PKPRCB Prcb ) { ......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!