创建线程小细节 笔记复习1
创建用户线程时
内核的trapframe开始执行的函数是KiThreadStartup
内核态KiThreadStartup得到CPU执行后,KiThreadStartup调用PspUserThreadStartup
而PspUserThreadStartup会设置一个用户的apc,ntdll!LdrInitializeThunk:
PspUserThreadStartup执行完成后,会返回用户空间,用户空间的执行函数是kernel32!BaseThreadStartThunk
但由于PspUserThreadStartup设置了一个APC,所以在返回用户空间之前会先执行APC,最后ntdll!LdrInitializeThunk先执行
根据APC的特征,ntdll!LdrInitializeThunk:执行完后,又回去了内核空间,内核空间马上返回用户空间,在返回过程中发现没有APC了,最后真的回到用户空间,
执行kernel32!BaseThreadStartThunk
==============
PspCreateProcessNotifyRoutine的调用是在 pspcreatethread()函数中,判断该线程是否是这个进程的第一个线程,是则调用PspCreateProcessNotifyRoutine,不是就调用CreateThread的Notify
另外,ntdll!LdrInitializeThunk不管是不是第一个线程,都会插入这个APC的,只是这个函数下面执行后会有不同的分支
这是线程
0213f578 77848968 kernel32!BaseDllInitialize+0x3
0213f598 77853820 ntdll!LdrpCallInitRoutine+0x14
0213f638 778535bc ntdll!LdrpInitializeThread+0x15b,这里会有TLS分配的调用
0213f684 778535e9 ntdll!_LdrpInitialize+0x1ad
0213f694 00000000 ntdll!LdrInitializeThunk+0x10
//这是进程
0:000> k
ChildEBP RetAddr
0014f838 77870e00 ntdll!LdrpDoDebuggerBreak+0x2c
0014f998 77856047 ntdll!LdrpInitializeProcess+0x11a9
0014f9e8 778535e9 ntdll!_LdrpInitialize+0x78
0014f9f8 00000000 ntdll!LdrInitializeThunk+0x10
可以看出,_LdrpInitialize会跳到不同的分支
这个跳转只要是根据ntdll全局变量LdrpProcessInitialized进行区分

浙公网安备 33010602011771号