• 从时钟中断到线程调度的分析(一)


     

          首先,时钟中断属于硬件中断,IRQL为28,仅次于蓝屏,电源和IPI,属于很高级别了,所以不知道接下来的调试会不会很顺利,不说了,试试看看

          擦,搜索了下,WRK居然没有时钟中断函数,看来不愧是阉割版,那看看reactos里面有没

    VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts)
    {
        ULONG_PTR EFlags;
    
        /* Save EFlags and disable interrupts */
        EFlags = __readeflags();
        _disable();  
    
        /* Initialize and mask the PIC */
        HalpInitializeLegacyPIC();
    
        /* Initialize the I/O APIC */
        ApicInitializeIOApic();
    
        /* Manually reserve some vectors */
        HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8;
        HalpVectorToIndex[APC_VECTOR] = 99;
        HalpVectorToIndex[DISPATCH_VECTOR] = 99;
    
        /* Set interrupt handlers in the IDT */
        KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt);  // 注册时钟中断函数
    #ifndef _M_AMD64
        KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt);           // 注册APC中断函数
        KeRegisterInterruptHandler(DISPATCH_VECTOR, HalpDispatchInterrupt); // 注册DPC中断函数
    #endif
    
        /* Register the vectors for APC and dispatch interrupts */
        HalpRegisterVector(IDT_INTERNAL, 0, APC_VECTOR, APC_LEVEL);
        HalpRegisterVector(IDT_INTERNAL, 0, DISPATCH_VECTOR, DISPATCH_LEVEL);
    
        /* Restore interrupt state */
        if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK;
        __writeeflags(EFlags);
    }

        阴差阳错,搜索HalpClockInterrupt时居然看到了时钟中断,APC,和DPC的注册过程,注册过程是HalpInitializePICs初始化的,那么这个函数又是被谁调用的呢,继续跟踪发现是在HalInitSystem中被调用的

    windows真不要脸,这个函数也没公布,只公布了原型:

         HalInitSystem (IN ULONG Phase,IN PLOADER_PARAMETER_BLOCK LoaderBlock);

    看原型,这跟Reactos中定义的一样啊,所以还是看看reactos吧:
    BOOLEAN NTAPI INIT_FUNCTION HalInitSystem(IN ULONG BootPhase,IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PKPRCB Prcb
    = KeGetCurrentPrcb(); /* Check the boot phase */ if (BootPhase == 0) // 看情况是阶段0初始化的时候,才能注册时钟中断 { /* Phase 0... save bus type */ HalpBusType = LoaderBlock->u.I386.MachineType & 0xFF; /* Get command-line parameters */ HalpGetParameters(LoaderBlock); /* Check for PRCB version mismatch */ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { /* No match, bugcheck */ KeBugCheckEx(MISMATCHED_HAL, 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0); } /* Checked/free HAL requires checked/free kernel */ if (Prcb->BuildType != HalpBuildType) { /* No match, bugcheck */ KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, HalpBuildType, 0); } /* Initialize ACPI */ HalpSetupAcpiPhase0(LoaderBlock); /* Initialize the PICs */ HalpInitializePICs(TRUE); // 这个函数会调用函数进行时钟中断,APC,DPC的注册 /* Initialize CMOS lock */ KeInitializeSpinLock(&HalpSystemHardwareLock); /* Initialize CMOS */ HalpInitializeCmos(); /* Fill out the dispatch tables */ HalQuerySystemInformation = HaliQuerySystemInformation; HalSetSystemInformation = HaliSetSystemInformation; HalInitPnpDriver = HaliInitPnpDriver; HalGetDmaAdapter = HalpGetDmaAdapter; HalGetInterruptTranslator = NULL; // FIXME: TODO HalResetDisplay = HalpBiosDisplayReset; HalHaltSystem = HaliHaltSystem; /* Setup I/O space */ HalpDefaultIoSpace.Next = HalpAddressUsageList; HalpAddressUsageList = &HalpDefaultIoSpace; /* Setup busy waiting */ HalpCalibrateStallExecution(); /* Initialize the clock */ HalpInitializeClock(); /* * We could be rebooting with a pending profile interrupt, * so clear it here before interrupts are enabled */ HalStopProfileInterrupt(ProfileTime); /* Do some HAL-specific initialization */ HalpInitPhase0(LoaderBlock); } else if (BootPhase == 1) { /* Initialize bus handlers */ HalpInitBusHandlers(); /* Do some HAL-specific initialization */ HalpInitPhase1(); } /* All done, return */ return TRUE; }

           至于HalInitSystem是什么,这个基本搞过内核的都知道,内核初始化的时候会调用这个函数,看了下Reactos是直接设置了入口点,所以回到WRK,看看HalInitSystem是什么时间调用的

    VOID ExpInitializeExecutive(IN ULONG Number,IN PLOADER_PARAMETER_BLOCK LoaderBlock) 
    {
      ......

        if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {
          KeBugCheck(HAL_INITIALIZATION_FAILED);
        }

      ......
    }

          跟到这里就没必要往上跟踪了,在往上就是内核入口函数了,这里附加一个内核原理与实现书上的一张图

     所以可以总结下时钟中断/APC/DPC注册的流程了:

       KiSystemStartUp->KiInitlizeKernel->ExpInitializeExecutive->HalInitSystem->HalpInitializePICs->注册中断

    好了,以上都是理论,现在测试下, 启动windbg,这里要设置系统初始断点,以上其他函数的执行过程省略,直接从ExpInitializeExecutive开始

    通过参数可以看到,传递给HalInitSystem的参数是0,代表是内核阶段0初始化,继续跟踪

    HalInitSystem会判断是阶段0还是阶段1,这里是阶段0,所以会调用HalpInitializePICs注册时钟中断,但是可能因为硬件的问题,调用的不是APIC.C中的HalpInitializePICs,而是PIC中的HalpInitializePICs,这里先不深究了

  • 相关阅读:
    Win7系统中打开exe 无反应
    IE 浏览器主页劫持 如何修复
    win10 airpods显示已配对,但就是连不上怎么办?
    tp5 layui 渲染 时间戳转换为日期时间格式
    为什么要设置 繁琐的密码
    美食摄影 – 明确目的
    MsMpEng.exe进程停止删除或弹出设备,导致移动硬盘无法正常弹出,怎么办?
    单抗热门靶点 | VEGF | TNF-α | CD20 | HER2 | PD-1 | IL-6R | CD47
    EZH2 | Ezh2 | 组蛋白甲基化酶/组蛋白甲基转移酶
    宇宙微波背景辐射 | 著名实验
  • 原文地址:https://www.cnblogs.com/testvt/p/5488777.html
Copyright © 2020-2023  润新知