微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

reactos操作系统实现(39)

到底一个线程是怎么样创建的呢?又是怎么样放到就绪队列呢?

#001 NTSTATUS

#002 NTAPI

#003 PspCreateThread(OUT PHANDLE ThreadHandle,

#004 IN ACCESS_MASK DesiredAccess,

#005 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

#006 IN HANDLE ProcessHandle,

#007 IN PEPROCESS TargetProcess,

#008 OUT PCLIENT_ID ClientId,

#009 IN PCONTEXT threadcontext,

#010 IN PINITIAL_TEB InitialTeb,

#011 IN BOOLEAN CreateSuspended,

#012 IN PKSTART_ROUTINE StartRoutine OPTIONAL,

#013 IN PVOID StartContext OPTIONAL)

#014 {

#015 HANDLE hThread;

#016 PEPROCESS Process;

#017 PETHREAD Thread;

#018 PTEB TebBase = NULL;

获取当前处理器的模式,比如内核模式、用户模式、最大模式。

#019 KPROCESSOR_MODE PrevIoUsMode = ExGetPrevIoUsMode();

#020 NTSTATUS Status,Accessstatus;

#021 HANDLE_TABLE_ENTRY CidEntry;

#022 ACCESS_STATE LocalAccessstate;

#023 PACCESS_STATE Accessstate = &LocalAccessstate;

#024 AUX_ACCESS_DATA AuxData;

#025 BOOLEAN Result,SdAllocated;

#026 PSecurity_DESCRIPTOR SecurityDescriptor;

#027 Security_SUBJECT_CONTEXT SubjectContext;

判断代码是否可以执行。

#028 PAGED_CODE();

#029 PSTRACE(PS_THREAD_DEBUG,

#030 "threadcontext: %p TargetProcess: %p ProcessHandle: %p/n",

#031 threadcontext,TargetProcess,ProcessHandle);

#032

当从函数PsCreateSystemThread调用时,当前肯定是运行在内核模式,也就是通过是否有回调函数StartRoutine来判断的。

#033 /* If we were called from PsCreateSystemThread,then we're kernel mode */

#034 if (StartRoutine) PrevIoUsMode = KernelMode;

#035

获取线程所属的进程结构。

#036 /* Reference the Process by handle or pointer,depending on what we got */

#037 if (ProcessHandle)

#038 {

通过进程句柄到对象

#039 /* normal thread or System Thread */

#040 Status = ObReferenceObjectByHandle(ProcessHandle,

#041 PROCESS_CREATE_THREAD,

#042 PsProcesstype,

#043 PrevIoUsMode,

#044 (PVOID*)&Process,

#045 NULL);

#046 PSREFTRACE(Process);

#047 }

#048 else

#049 {

获取系统线程的进程对象,或者普通线程的进程有问题。

#050 /* System thread inside System Process,or normal Thread with a bug */

#051 if (StartRoutine)

#052 {

#053 /* Reference the Process by Pointer */

#054 ObReferenceObject(TargetProcess);

#055 Process = TargetProcess;

#056 Status = STATUS_SUCCESS;

#057 }

#058 else

#059 {

#060 /* Fake ObReference returning this */

#061 Status = STATUS_INVALID_HANDLE;

#062 }

#063 }

#064

#065 /* Check for success */

#066 if (!NT_SUCCESS(Status)) return Status;

#067

如果不是内核模式,不让创建线程。

#068 /* Also make sure that User-Mode isn't trying to create a system thread */

#069 if ((PrevIoUsMode != KernelMode) && (Process == PsInitialSystemProcess))

#070 {

#071 /* Fail */

#072 ObDereferenceObject(Process);

#073 return STATUS_INVALID_HANDLE;

#074 }

#075

创建一个线程对象。

#076 /* Create Thread Object */

#077 Status = ObCreateObject(PrevIoUsMode,

#078 PsThreadType,

#079 ObjectAttributes,

#080 PrevIoUsMode,

#081 NULL,

#082 sizeof(ETHREAD),

#083 0,

#084 0,

#085 (PVOID*)&Thread);

#086 if (!NT_SUCCESS(Status))

#087 {

#088 /* We Failed; dereference the process and exit */

#089 ObDereferenceObject(Process);

#090 return Status;

#091 }

#092

初始化线程对象。

#093 /* Zero the Object entirely */

#094 RtlZeroMemory(Thread,sizeof(ETHREAD));

#095

#096 /* Initialize rundown protection */

#097 ExInitializeRundownProtection(&Thread->RundownProtect);

#098

设置线程退出码。

#099 /* Initialize exit code */

#100 Thread->ExitStatus = STATUS_PENDING;

#101

设置线程的进程ID

#102 /* Set the Process CID */

#103 Thread->ThreadsProcess = Process;

#104 Thread->Cid.UniqueProcess = Process->UniqueProcessId;

#105

创建线程的ID

#106 /* Create Cid Handle */

#107 CidEntry.Object = Thread;

#108 CidEntry.GrantedAccess = 0;

#109 Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable,&CidEntry);

#110 if (!Thread->Cid.UniqueThread)

#111 {

#112 /* We Couldn't create the CID,dereference the thread and fail */

#113 ObDereferenceObject(Thread);

#114 return STATUS_INSUFFICIENT_RESOURCES;

#115 }

保存读取的族大小。

#116

#117 /* Save the read cluster size */

#118 Thread->ReadClusterSize = MmReadClusterSize;

#119

初始化LPC信号量。

#120 /* Initialize the LPC Reply Semaphore */

#121 KeInitializeSemaphore(&Thread->LpcReplySemaphore,1);

#122

初始化线程的列表和锁。

#123 /* Initialize the list heads and locks */

#124 InitializeListHead(&Thread->LpcReplyChain);

#125 InitializeListHead(&Thread->IrpList);

#126 InitializeListHead(&Thread->PostBlockList);

#127 InitializeListHead(&Thread->ActiveTimerListHead);

#128 KeInitializeSpinLock(&Thread->ActiveTimerListLock);

#129

#130 /* Acquire rundown protection */

#131 if (!ExAcquireRundownProtection (&Process->RundownProtect))

#132 {

#133 /* Fail */

#134 ObDereferenceObject(Thread);

#135 return STATUS_PROCESS_IS_TERMINATING;

#136 }

#137

初始化线程的TEB环境块。

#138 /* Now let the kernel initialize the context */

#139 if (threadcontext)

#140 {

#141 /* User-mode Thread,create Teb */

#142 TebBase = MmCreateTeb(Process,&Thread->Cid,InitialTeb);

#143 if (!TebBase)

#144 {

#145 /* Failed to create the TEB. Release rundown and dereference */

#146 ExReleaseRundownProtection(&Process->RundownProtect);

#147 ObDereferenceObject(Thread);

#148 return STATUS_INSUFFICIENT_RESOURCES;

#149 }

#150

#151 /* Set the Start Addresses */

#152 #if defined(_M_IX86)

#153 Thread->StartAddress = (PVOID)threadcontext->Eip;

#154 Thread->Win32StartAddress = (PVOID)threadcontext->Eax;

#155 #elif defined(_M_PPC)

#156 Thread->StartAddress = (PVOID)threadcontext->Dr0;

#157 Thread->Win32StartAddress = (PVOID)threadcontext->Gpr3;

#158 #elif defined(_M_MIPS)

#159 Thread->StartAddress = (PVOID)threadcontext->Psr;

#160 Thread->Win32StartAddress = (PVOID)threadcontext->IntA0;

#161 #elif defined(_M_ARM)

#162 Thread->StartAddress = (PVOID)threadcontext->Pc;

#163 Thread->Win32StartAddress = (PVOID)threadcontext->R0;

#164 #elif defined(_M_AMD64)

#165 Thread->StartAddress = (PVOID)threadcontext->Rip;

#166 Thread->Win32StartAddress = (PVOID)threadcontext->Rax;

#167 #else

#168 #error UnkNown architecture

#169 #endif

#170

#171 /* Let the kernel intialize the Thread */

#172 Status = KeInitThread(&Thread->Tcb,

#173 NULL,

#174 PspUserThreadStartup,

#175 NULL,

#176 Thread->StartAddress,

#177 threadcontext,

#178 TebBase,

#179 &Process->Pcb);

#180 }

#181 else

#182 {

创建系统线程。

#183 /* System Thread */

#184 Thread->StartAddress = StartRoutine;

#185 PspSetCrossthreadFlag(Thread,CT_SYstem_THREAD_BIT);

#186

#187 /* Let the kernel intialize the Thread */

#188 Status = KeInitThread(&Thread->Tcb,

#189 NULL,

#190 PspSystemThreadStartup,

#191 StartRoutine,

#192 StartContext,

#193 NULL,

#194 NULL,

#195 &Process->Pcb);

#196 }

#197

初始化线程失败,就清除分配的资源。

#198 /* Check if we Failed */

#199 if (!NT_SUCCESS(Status))

#200 {

#201 /* Delete the TEB if we had done */

#202 if (TebBase) MmDeleteTeb(Process,TebBase);

#203

#204 /* Release rundown and dereference */

#205 ExReleaseRundownProtection(&Process->RundownProtect);

#206 ObDereferenceObject(Thread);

#207 return Status;

#208 }

#209

检查进程是否已经删除

#210 /* Lock the process */

#211 KeEnterCriticalRegion();

#212 ExAcquirePushLockExclusive(&Process->ProcessLock);

#213

#214 /* Make sure the proces didn't just die on us */

#215 if (Process->ProcessDelete) goto Quickie;

#216

#217 /* Check if the thread was ours,terminated and it was user mode */

#218 if ((Thread->Terminated) &&

#219 (threadcontext) &&

#220 (Thread->ThreadsProcess == Process))

#221 {

#222 /* Cleanup,we don't want to start it up and context switch */

#223 goto Quickie;

#224 }

#225

把新创建的线程放到进程的线程列表里。

#226 /*

#227 * Insert the Thread into the Process's Thread List

#228 * Note,this is the ETHREAD Thread List. It is removed in

#229 * ps/kill.c!PspExitThread.

#230 */

#231 InsertTailList(&Process->ThreadListHead,&Thread->ThreadListEntry);

#232 Process->ActiveThreads++;

#233

设置启动线程。

#234 /* Start the thread */

#235 KeStartThread(&Thread->Tcb);

#236

#237 /* Release the process lock */

#238 ExReleasePushLockExclusive(&Process->ProcessLock);

#239 KeLeaveCriticalRegion();

#240

#241 /* Release rundown */

#242 ExReleaseRundownProtection(&Process->RundownProtect);

#243

#244 /* Notify WMI */

#245 //WmiTraceProcess(Process,TRUE);

#246 //WmiTraceThread(Thread,InitialTeb,TRUE);

#247

通知线程创建。

#248 /* Notify Thread Creation */

#249 PspruncreateThreadNotifyRoutines(Thread,TRUE);

#250

#251 /* Reference ourselves as a keep-alive */

#252 ObReferenceObjectEx(Thread,2);

#253

检查是否需要挂起线程执行。

#254 /* Suspend the Thread if we have to */

#255 if (CreateSuspended) KeSuspendThread(&Thread->Tcb);

#256

终止线程的执行。

#257 /* Check if we were already terminated */

#258 if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);

#259

#260 /* Create an access state */

#261 Status = SeCreateAccessstateEx(NULL,

#262 threadcontext ?

#263 PsGetCurrentProcess() : Process,

#264 &LocalAccessstate,

#265 &AuxData,

#266 DesiredAccess,

#267 &PsThreadType->TypeInfo.GenericMapping);

#268 if (!NT_SUCCESS(Status))

#269 {

#270 /* Access state Failed,thread is dead */

#271 PspSetCrossthreadFlag(Thread,CT_DEAD_THREAD_BIT);

#272

#273 /* If we were suspended,wake it up */

#274 if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#275

#276 /* dispatch thread */

#277 KeReadyThread(&Thread->Tcb);

#278

#279 /* Dereference completely to kill it */

#280 ObDereferenceObjectEx(Thread,2);

#281 return Status;

#282 }

#283

把线程放到对象管理器。

#284 /* Insert the Thread into the Object Manager */

#285 Status = ObInsertObject(Thread,

#286 Accessstate,

#287 DesiredAccess,

#288 0,

#289 NULL,

#290 &hThread);

#291

#292 /* Delete the access state if we had one */

#293 if (Accessstate) SeDeleteAccessstate(Accessstate);

#294

通过SEH机制保存线程ID和线程句柄给用户间的变量。

#295 /* Check for success */

#296 if (NT_SUCCESS(Status))

#297 {

#298 /* Wrap in SEH to protect against bad user-mode pointers */

#299 _SEH2_TRY

#300 {

#301 /* Return Cid and Handle */

#302 if (ClientId) *ClientId = Thread->Cid;

#303 *ThreadHandle = hThread;

#304 }

#305 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)

#306 {

#307 /* Get the exception code */

#308 Status = _SEH2_GetExceptionCode();

#309

#310 /* Thread insertion Failed,thread is dead */

#311 PspSetCrossthreadFlag(Thread,CT_DEAD_THREAD_BIT);

#312

#313 /* If we were suspended,wake it up */

#314 if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#315

#316 /* dispatch thread */

#317 KeReadyThread(&Thread->Tcb);

#318

#319 /* Dereference it,leaving only the keep-alive */

#320 ObDereferenceObject(Thread);

#321

#322 /* Close its handle,killing it */

#323 ObCloseHandle(ThreadHandle,PrevIoUsMode);

#324 }

#325 _SEH2_END;

#326 if (!NT_SUCCESS(Status)) return Status;

#327 }

#328 else

#329 {

#330 /* Thread insertion Failed,thread is dead */

#331 PspSetCrossthreadFlag(Thread,CT_DEAD_THREAD_BIT);

#332

#333 /* If we were suspended,wake it up */

#334 if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#335 }

#336

获取线程创建时间。

#337 /* Get the create time */

#338 KeQuerySystemTime(&Thread->CreateTime);

#339 ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));

#340

#341 /* Make sure the thread isn't dead */

#342 if (!Thread->DeadThread)

#343 {

#344 /* Get the thread's SD */

#345 Status = ObGetobjectSecurity(Thread,

#346 &SecurityDescriptor,

#347 &SdAllocated);

#348 if (!NT_SUCCESS(Status))

#349 {

#350 /* Thread insertion Failed,thread is dead */

#351 PspSetCrossthreadFlag(Thread,CT_DEAD_THREAD_BIT);

#352

#353 /* If we were suspended,wake it up */

#354 if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#355

#356 /* dispatch thread */

#357 KeReadyThread(&Thread->Tcb);

#358

#359 /* Dereference it,leaving only the keep-alive */

#360 ObDereferenceObject(Thread);

#361

#362 /* Close its handle,killing it */

#363 ObCloseHandle(ThreadHandle,PrevIoUsMode);

#364 return Status;

#365 }

#366

设置线程安全环境变量。

#367 /* Create the subject context */

#368 SubjectContext.ProcessAuditId = Process;

#369 SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);

#370 SubjectContext.ClientToken = NULL;

#371

#372 /* Do the access check */

#373 Result = SeAccessCheck(SecurityDescriptor,

#374 &SubjectContext,

#375 FALSE,

#376 MAXIMUM_ALLOWED,

#377 0,

#378 NULL,

#379 &PsThreadType->TypeInfo.GenericMapping,

#380 PrevIoUsMode,

#381 &Thread->GrantedAccess,

#382 &Accessstatus);

#383

#384 /* Dereference the token and let go the SD */

#385 ObFastDereferenceObject(&Process->Token,

#386 SubjectContext.PrimaryToken);

#387 ObReleaSEObjectSecurity(SecurityDescriptor,SdAllocated);

#388

#389 /* Remove access if it Failed */

#390 if (!Result) Process->GrantedAccess = 0;

#391

#392 /* Set least some minimum access */

#393 Thread->GrantedAccess |= (THREAD_TERMINATE |

#394 THREAD_SET_informatION |

#395 THREAD_QUERY_informatION);

#396 }

#397 else

#398 {

#399 /* Set the thread access mask to maximum */

#400 Thread->GrantedAccess = THREAD_ALL_ACCESS;

#401 }

#402

标记线程已经可以运行,把线程放到准备就绪队列。

#403 /* dispatch thread */

#404 KeReadyThread(&Thread->Tcb);

#405

#406 /* Dereference it,leaving only the keep-alive */

#407 ObDereferenceObject(Thread);

#408

#409 /* Return */

#410 return Status;

#411

出错处理。

#412 /* Most annoying failure case ever,where we undo almost all manually */

#413 Quickie:

#414 /* When we get here,the process is locked,unlock it */

#415 ExReleasePushLockExclusive(&Process->ProcessLock);

#416 KeLeaveCriticalRegion();

#417

#418 /* Uninitailize it */

#419 KeUninitThread(&Thread->Tcb);

#420

#421 /* If we had a TEB,delete it */

#422 if (TebBase) MmDeleteTeb(Process,TebBase);

#423

#424 /* Release rundown protection,which we also hold */

#425 ExReleaseRundownProtection(&Process->RundownProtect);

#426

#427 /* Dereference the thread and return failure */

#428 ObDereferenceObject(Thread);

#429 return STATUS_PROCESS_IS_TERMINATING;

#430 }

通上面函数分析,已经了解一个线程创建,不但可以创建系统线程,还可以创建用户线程。当初始化线程后,就可以把线程放到调度就绪队列,准备给下一轮调试使用。

原文地址:https://www.jb51.cc/react/308494.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐