selph
selph
发布于 2021-10-31 / 448 阅读
0
0

Windows 进程与线程的初始化过程分析--基于Windows XP源码

进程初始化过程

初始化进程:KeInitializeProcess(位于XP源码:NT/base/ntos/ke/procobj.c

  • 初始化对象类型:进程对象
  • 初始化等待链表
  • 初始化K/EPROCESS基础字段:基础优先级,亲核性,页表,栈
  • 初始化三个链表(ProfileListHead、就绪线程链表ReadyListHead、线程链表ThreadListHead)
  • 初始化进程状态

这个函数主要是填充EPROCESS基本结构

KeInitializeProcess

VOID
KeInitializeProcess (
    IN PRKPROCESS Process,
    IN KPRIORITY BasePriority,
    IN KAFFINITY Affinity,
    IN ULONG_PTR DirectoryTableBase[2],
    IN BOOLEAN Enable
    ) 

/*++

Routine Description:

    This function initializes a kernel process object. The base priority,
    affinity, and page frame numbers for the process page table directory
    and hyper space are stored in the process object.
    这个函数初始化了一个内核进程对象
    往进程对象里保存了基本的优先级,亲核性,进程页表

    N.B. It is assumed that the process object is zeroed.
    牛逼,假设进程对象是空的
    
Arguments:

    Process - Supplies a pointer to a dispatcher object of type process.

    BasePriority - Supplies the base priority of the process.

    Affinity - Supplies the set of processors on which children threads
        of the process can execute.

    DirectoryTableBase - Supplies a pointer to an array whose fist element
        is the value that is to be loaded into the Directory Table Base
        register when a child thread is dispatched for execution and whose
        second element contains the page table entry that maps hyper space.

    Enable - Supplies a boolean value that determines the default
        handling of data alignment exceptions for child threads. A value
        of TRUE causes all data alignment exceptions to be automatically
        handled by the kernel. A value of FALSE causes all data alignment
        exceptions to be actually raised as exceptions.

Return Value:

    None.

--*/

{

    PKNODE Node;
    UCHAR NodeNumber;
    ULONG i;

    //
    // Initialize the standard dispatcher object header and set the initial
    // signal state of the process object.
    //
    // Process:KPROCESS结构第一个成员Dispatcher_header结构
    // 初始化进程类型:进程对象
    Process->Header.Type = ProcessObject;
    // 计算KPROCESS大小
    Process->Header.Size = sizeof(KPROCESS) / sizeof(LONG);
    // 初始化等待链表
    InitializeListHead(&Process->Header.WaitListHead);

    //
    // Initialize the base priority, affinity, directory table base values,
    // autoalignment, and stack count.
    //
    // N.B. The distinguished value MAXSHORT is used to signify that no
    //      threads have been created for the process.
    //
    // 初始化K/EPROCESS基础字段
    Process->BasePriority = (SCHAR)BasePriority;    // 基础优先级
    Process->Affinity = Affinity;   // 亲核性
    Process->AutoAlignment = Enable;    
    Process->DirectoryTableBase[0] = DirectoryTableBase[0]; // 页表
    Process->DirectoryTableBase[1] = DirectoryTableBase[1]; // 页表
    Process->StackCount = MAXSHORT; // 栈

    //
    // Initialize the stack count, profile listhead, ready queue list head,
    // accumulated runtime, process quantum, thread quantum, and thread list
    // head.
    //
    // 初始化三个链表
    InitializeListHead(&Process->ProfileListHead);
    InitializeListHead(&Process->ReadyListHead);
    InitializeListHead(&Process->ThreadListHead);
    Process->ThreadQuantum = THREAD_QUANTUM;

    //
    // Initialize the process state and set the thread processor selection
    // seed.
    //
    // 初始化进程状态
    Process->State = ProcessInMemory;

    //
    // Set the ideal node for this process.
    //

#if defined(KE_MULTINODE)
    // 检测操作系统有几个node,全局变量,默认是1
    if (KeNumberNodes > 1) {
        NodeNumber = (KeProcessNodeSeed + 1) % KeNumberNodes;
        KeProcessNodeSeed = NodeNumber;
        for (i = 0; i < KeNumberNodes; i++) {
            if (KeNodeBlock[NodeNumber]->ProcessorMask & Affinity) {
                break;
            }

            NodeNumber = (NodeNumber + 1) % KeNumberNodes;
        }

    } else {
        NodeNumber = 0;
    }
    // 全局变量获取nodeNumber
    Process->IdealNode = NodeNumber;
    // 取出node结点
    Node = KeNodeBlock[NodeNumber];
    // 寻找匹配的亲核性
    Process->ThreadSeed = KeFindNextRightSetAffinity(Node->Seed,
                                                     Node->ProcessorMask & Affinity);

    Node->Seed = Process->ThreadSeed;

#else
    // 通过API取摸
    Process->ThreadSeed = (UCHAR)KiQueryLowTickCount() % KeNumberProcessors;

#endif

    //
    // Initialize IopmBase and Iopl flag for this process (i386 only)
    //

#if defined(_X86_) || defined(_AMD64_)

    Process->IopmOffset = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);

#endif // defined(_X86_) || defined(_AMD64_)

    return;
}

线程初始化过程

初始化线程:KeInitThread(位于XP源码:NT/base/ntos/ke/thredobj.c

  • 初始化对象类型:线程对象
  • 线程切换相关字段初始化
  • 设置线程的SSDT
  • APC相关字段初始化
  • APC初始化
  • 同步相关初始化
  • 等待块初始化
  • 设置线程理想核心
  • 创建内核栈

这里主要是填充THREAD结构体

KeInitThread

NTSTATUS
KeInitThread (
    IN PKTHREAD Thread,
    IN PVOID KernelStack OPTIONAL,
    IN PKSYSTEM_ROUTINE SystemRoutine,
    IN PKSTART_ROUTINE StartRoutine OPTIONAL,
    IN PVOID StartContext OPTIONAL,
    IN PCONTEXT ContextFrame OPTIONAL,
    IN PVOID Teb OPTIONAL,
    IN PKPROCESS Process
    )

/*++

Routine Description:

    This function initializes a thread object. The priority, affinity,
    and initial quantum are taken from the parent process object.
    这个函数初始化一个线程对象,优先级、亲核性,初始量都从父进程那里取

    N.B. This routine is carefully written so that if an access violation
        occurs while reading the specified context frame, then no kernel
        data structures will have been modified. It is the responsibility
        of the caller to handle the exception and provide necessary clean
        up.

    N.B. It is assumed that the thread object is zeroed.

Arguments:

    Thread - Supplies a pointer to a dispatcher object of type thread.

    KernelStack - Supplies a pointer to the base of a kernel stack on which
        the context frame for the thread is to be constructed.

    SystemRoutine - Supplies a pointer to the system function that is to be
        called when the thread is first scheduled for execution.

    StartRoutine - Supplies an optional pointer to a function that is to be
        called after the system has finished initializing the thread. This
        parameter is specified if the thread is a system thread and will
        execute totally in kernel mode.

    StartContext - Supplies an optional pointer to an arbitrary data structure
        which will be passed to the StartRoutine as a parameter. This
        parameter is specified if the thread is a system thread and will
        execute totally in kernel mode.

    ContextFrame - Supplies an optional pointer a context frame which contains
        the initial user mode state of the thread. This parameter is specified
        if the thread is a user thread and will execute in user mode. If this
        parameter is not specified, then the Teb parameter is ignored.

    Teb - Supplies an optional pointer to the user mode thread environment
        block. This parameter is specified if the thread is a user thread and
        will execute in user mode. This parameter is ignored if the ContextFrame
        parameter is not specified.

    Process - Supplies a pointer to a control object of type process.

Return Value:

    None.

--*/

{

    UCHAR IdealProcessor;
    ULONG Index;
    BOOLEAN KernelStackAllocated = FALSE;
    KAFFINITY PreferredSet;
    NTSTATUS Status = STATUS_SUCCESS;
    KAFFINITY TempSet;
    PKTIMER Timer;
    PKWAIT_BLOCK WaitBlock;

    //
    // Initialize the standard dispatcher object header and set the initial
    // state of the thread object.
    // 初始化线程对象

    Thread->Header.Type = ThreadObject;
    Thread->Header.Size = sizeof(KTHREAD) / sizeof(LONG);
    InitializeListHead(&Thread->Header.WaitListHead);

    //
    // Initialize the owned mutant listhead.
    // 初始化链表

    InitializeListHead(&Thread->MutantListHead);

    //
    // Initialize the thread field of all builtin wait blocks.
    // 初始化等待块

    for (Index = 0; Index < (THREAD_WAIT_OBJECTS + 1); Index += 1) {
        Thread->WaitBlock[Index].Thread = Thread;
    }

    //
    // Initialize the alerted, preempted, debugactive, autoalignment,
    // kernel stack resident, enable kernel stack swap, and process
    // ready queue boolean values.
    //
    // N.B. Only nonzero values are initialized.
    // 

    Thread->AutoAlignment = Process->AutoAlignment;
    // 线程切换用的东西,做准备
    Thread->EnableStackSwap = TRUE;
    Thread->KernelStackResident = TRUE;

    //
    // Set the system service table pointer to the address of the static
    // system service descriptor table. If the thread is later converted
    // to a Win32 thread this pointer will be change to a pointer to the
    // shadow system service descriptor table.
    // 设置线程的SSDT

    Thread->ServiceTable = (PVOID)&KeServiceDescriptorTable[0];

    //
    // Initialize the APC state pointers, the current APC state, the saved
    // APC state, and enable APC queuing.
    // APC相关字段初始化

    Thread->ApcStatePointer[0] = &Thread->ApcState;
    Thread->ApcStatePointer[1] = &Thread->SavedApcState;
    InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
    InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
    Thread->ApcState.Process = Process;
    Thread->ApcQueueable = TRUE;

    //
    // Initialize the kernel mode suspend APC and the suspend semaphore object.
    // and the builtin wait timeout timer object.
    // APC初始化

    KeInitializeApc(&Thread->SuspendApc,
                    Thread,
                    OriginalApcEnvironment,
                    (PKKERNEL_ROUTINE)KiSuspendNop,
                    (PKRUNDOWN_ROUTINE)KiSuspendRundown,
                    KiSuspendThread,
                    KernelMode,
                    NULL);

    KeInitializeSemaphore(&Thread->SuspendSemaphore, 0L, 2L);

    //
    // Initialize the builtin timer trimer wait wait block.
    //
    // N.B. This is the only time the wait block is initialized sincs this
    //      information is constant.
    //
    // 设置定时器
    Timer = &Thread->Timer;
    KeInitializeTimer(Timer);
    // 初始化等待块
    WaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
    WaitBlock->Object = Timer;
    WaitBlock->WaitKey = (CSHORT)STATUS_TIMEOUT;
    WaitBlock->WaitType = WaitAny;
    WaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead;
    WaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead;

    //
    // Initialize the APC queue spinlock.
    // 初始化APC锁

    KeInitializeSpinLock(&Thread->ApcQueueLock);

    //
    // Initialize the Thread Environment Block (TEB) pointer (can be NULL).
    // 设置Teb

    Thread->Teb = Teb;

#if defined(NT_UP)
    // 设置了一个核心是0
    IdealProcessor = 0;

#else

    //
    // Initialize the ideal processor number for the thread.
    //
    // Set IdealProcessor to next processor this thread is allowed to
    // run on.
    //
    // Get a bit mask of the affinity of all processors with a smaller
    // number than the last processor assigned to this process.
    //
    // 设置线程理想核心
    IdealProcessor = Process->ThreadSeed;
    PreferredSet = Process->Affinity & KeActiveProcessors;

    //
    // If possible bias the ideal processor to a different SMT set than the
    // last thread.
    //

#if defined(NT_SMT)
    // 核心相关的获取
    TempSet = ~KiProcessorBlock[IdealProcessor]->MultiThreadProcessorSet;
    if ((PreferredSet & TempSet) != 0) {
        PreferredSet &= TempSet;
    }

#endif

    //
    // For NUMA systems bias the ideal processor to the same node as other
    // threads in the process.
    //

#if defined(KE_MULTINODE)

    TempSet = KeNodeBlock[Process->IdealNode]->ProcessorMask;
    if ((PreferredSet & TempSet) != 0) {
        PreferredSet &= TempSet;
    }

#endif

    IdealProcessor = KeFindNextRightSetAffinity(IdealProcessor,
                                                PreferredSet);

#endif

    //
    // Set the initial node which is used for stack allocation and delete.
    // This needs to be determined as it may not have been possible to put
    // the thread on its ideal node.
    //

#if defined(KE_MULTINODE)

    for (Index = Process->IdealNode;
         (KeNodeBlock[Index]->ProcessorMask & AFFINITY_MASK(IdealProcessor)) == 0;
         Index = Index > 0 ? Index - 1 : KeNumberNodes - 1) {
        if (Process->IdealNode == Index) {

            //
            // This can only happen if we wrapped,... which can't happen.
            //

            Index = 0;
            break;
        }
    }

    Thread->InitialNode = (UCHAR)Index;

#else

    Thread->InitialNode = 0;

#endif

    //
    // Set the initial kernel stack and the initial thread context.
    //
    // 内核栈判断
    if (KernelStack == NULL) {

        //
        // Get a kernel stack for this thread.
        //
        // 创建内核栈
        KernelStack = MmCreateKernelStack(FALSE, Thread->InitialNode);
        if (KernelStack == NULL) {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        KernelStackAllocated = TRUE;
    }
    // 设置栈相关字段,内核栈,栈底,栈长度(栈顶)
    Thread->InitialStack = KernelStack;
    Thread->StackBase = KernelStack;
    Thread->StackLimit = (PVOID)((ULONG_PTR)KernelStack - KERNEL_STACK_SIZE);
    try {
        // 初始化线程上下文CONTEXT TRAP_FRAME
        KiInitializeContextThread(Thread,
                                  SystemRoutine,
                                  StartRoutine,
                                  StartContext,
                                  ContextFrame);

    } except (EXCEPTION_EXECUTE_HANDLER) {
        if (KernelStackAllocated) {
            MmDeleteKernelStack(Thread->StackBase, FALSE);
            Thread->InitialStack = NULL;
        }

        return GetExceptionCode();
    }

    //
    // Set the base thread priority, the thread priority, the thread affinity,
    // the thread quantum, and the scheduling state.
    //

    Thread->State = Initialized;

#if defined(NT_UP)
    // 设置理想核心 亲核性
    Thread->IdealProcessor = 0;
    Thread->SoftAffinity = 1;

#else

    Thread->IdealProcessor = IdealProcessor;

#endif

    return STATUS_SUCCESS;
}

评论