reactos操作系统实现(37)
下面来继续分析创建进程函数,过程如下: 保存工作集数据。 #070 /* Save working set data */ #071 MinWs = PsMinimumWorkingSet; #072 MaxWs = PsMaximumWorkingSet; #073
创建一个进程对象。 #074 /* Create the Object */ #075 Status = ObCreateObject(PreviousMode, #076 PsProcessType, #077 ObjectAttributes, #078 PreviousMode, #079 NULL, #080 sizeof(EPROCESS), #081 0, #082 0, #083 (PVOID*)&Process); #084 if (!NT_SUCCESS(Status)) goto Cleanup; #085
清空对象结构。 #086 /* Clean up the Object */ #087 RtlZeroMemory(Process,sizeof(EPROCESS)); #088
#089 /* Initialize pushlock and rundown protection */ #090 ExInitializeRundownProtection(&Process->RundownProtect); #091 Process->ProcessLock.Value = 0; #092
创建进程的列表,用来保存这个进程的线程。 #093 /* Setup the Thread List Head */ #094 InitializeListHead(&Process->ThreadListHead); #095
从父进程获取一定的配额块。 #096 /* Set up the Quota Block from the Parent */ #097 PspInheritQuota(Process,Parent); #098
从父进程获取DOS设备位图。 #099 /* Set up Dos Device Map from the Parent */ #100 ObInheritDeviceMap(Parent,Process); #101
判断是否有父进程。 #102 /* Check if we have a parent */ #103 if (Parent) #104 { #105 /* Ineherit PID and Hard Error Processing */ #106 Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId; #107 Process->DefaultHardErrorProcessing = Parent-> #108 DefaultHardErrorProcessing; #109 } #110 else #111 { #112 /* Use default hard error processing */ #113 Process->DefaultHardErrorProcessing = TRUE; #114 } #115
判断是否有段句柄。 #116 /* Check for a section handle */ #117 if (SectionHandle) #118 { #119 /* Get a pointer to it */ #120 Status = ObReferenceObjectByHandle(SectionHandle, #121 SECTION_MAP_EXECUTE, #122 MmSectionObjectType, #123 PreviousMode, #124 (PVOID*)&SectionObject, #125 NULL); #126 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #127 } #128 else #129 { #130 /* Assume no section object */ #131 SectionObject = NULL; #132 #133 /* Is the parent the initial process? */ #134 if (Parent != PsInitialSystemProcess) #135 { #136 /* It's not,so acquire the process rundown */ #137 if (ExAcquireRundownProtection(&Process->RundownProtect)) #138 { #139 /* If the parent has a section,use it */ #140 SectionObject = Parent->SectionObject; #141 if (SectionObject) ObReferenceObject(SectionObject); #142 #143 /* Release process rundown */ #144 ExReleaseRundownProtection(&Process->RundownProtect); #145 } #146 #147 /* If we don't have a section object */ #148 if (!SectionObject) #149 { #150 /* Then the process is in termination,so fail */ #151 Status = STATUS_PROCESS_IS_TERMINATING; #152 goto CleanupWithRef; #153 } #154 } #155 } #156
保存段句柄。 #157 /* Save the pointer to the section object */ #158 Process->SectionObject = SectionObject; #159
检查是否有调试输出端口。 #160 /* Check for the debug port */ #161 if (DebugPort) #162 { #163 /* Reference it */ #164 Status = ObReferenceObjectByHandle(DebugPort, #165 DEBUG_OBJECT_ADD_REMOVE_PROCESS, #166 DbgkDebugObjectType, #167 PreviousMode, #168 (PVOID*)&DebugObject, #169 NULL); #170 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #171 #172 /* Save the debug object */ #173 Process->DebugPort = DebugObject; #174 #175 /* Check if the caller doesn't want the debug stuff inherited */ #176 if (Flags & PS_NO_DEBUG_INHERIT) #177 { #178 /* Set the process flag */ #179 InterlockedOr((PLONG)&Process->Flags,PSF_NO_DEBUG_INHERIT_BIT); #180 } #181 } #182 else #183 { #184 /* Do we have a parent? Copy his debug port */ #185 if (Parent) DbgkCopyProcessDebugPort(Process,Parent); #186 } #187
检查是否有异常输出端口。 #188 /* Now check for an exception port */ #189 if (ExceptionPort) #190 { #191 /* Reference it */ #192 Status = ObReferenceObjectByHandle(ExceptionPort, #193 PORT_ALL_ACCESS, #194 LpcPortObjectType, #195 PreviousMode, #196 (PVOID*)&ExceptionPortObject, #197 NULL); #198 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #199 #200 /* Save the exception port */ #201 Process->ExceptionPort = ExceptionPortObject; #202 } #203 #204 /* Save the pointer to the section object */ #205 Process->SectionObject = SectionObject; #206
保存进程退出码。 #207 /* Set default exit code */ #208 Process->ExitStatus = STATUS_TIMEOUT; #209
检查是否有父进程。 #210 /* Check if this is the initial process being built */ #211 if (Parent) #212 {
如果有父进程,就创建子进程空间。 #213 /* Create the address space for the child */ #214 if (!MmCreateProcessAddressSpace(MinWs, #215 Process, #216 DirectoryTableBase)) #217 { #218 /* Failed */ #219 Status = STATUS_INSUFFICIENT_RESOURCES; #220 goto CleanupWithRef; #221 } #222 } #223 else #224 { #225 /* Otherwise,we are the boot process,we're already semi-initialized */ #226 Process->ObjectTable = CurrentProcess->ObjectTable; #227 Status = MmInitializeHandBuiltProcess(Process,DirectoryTableBase); #228 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #229 } #230
设置进程已经分配了内存。 #231 /* We now have an address space */ #232 InterlockedOr((PLONG)&Process->Flags,PSF_HAS_ADDRESS_SPACE_BIT); #233 #234 /* Set the maximum WS */ #235 Process->Vm.MaximumWorkingSetSize = MaxWs; #236
调用函数KeInitializeProcess来初始化内核进程块。 #237 /* Now initialize the Kernel Process */ #238 KeInitializeProcess(&Process->Pcb, #239 PROCESS_PRIORITY_NORMAL, #240 Affinity, #241 DirectoryTableBase, #242 (BOOLEAN)(Process->DefaultHardErrorProcessing & 4)); #243
继承父进程的安全属性。 #244 /* Duplicate Parent Token */ #245 Status = PspInitializeProcessSecurity(Process,Parent); #246 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #247
设置进程调试优先级。 #248 /* Set default priority class */ #249 Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; #250
根据父进程来微调进程的调试优先级。 #251 /* Check if we have a parent */ #252 if (Parent) #253 { #254 /* Check our priority class */ #255 if (Parent->PriorityClass == PROCESS_PRIORITY_CLASS_IDLE || #256 Parent->PriorityClass == PROCESS_PRIORITY_CLASS_BELOW_NORMAL) #257 { #258 /* Normalize it */ #259 Process->PriorityClass = Parent->PriorityClass; #260 } #261 #262 /* Initialize object manager for the process */ #263 Status = ObInitProcess(Flags & PS_INHERIT_HANDLES ? Parent : NULL, #264 Process); #265 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #266 } #267 else #268 { #269 /* Do the second part of the boot process memory setup */ #270 Status = MmInitializeHandBuiltProcess2(Process); #271 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #272 } #273
到这里已经创建进程成功了。 #274 /* Set success for now */ #275 Status = STATUS_SUCCESS; #276
检查是否用户模式进程。 #277 /* Check if this is a real user-mode process */ #278 if (SectionHandle) #279 {
创建用户模式进程的空间。 #280 /* Initialize the address space */ #281 Status = MmInitializeProcessAddressSpace(Process, #282 NULL, #283 SectionObject, #284 &Flags, #285 &Process-> #286 SeAuditProcessCreationInfo. #287 ImageFileName); #288 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #289 } #290 else if (Parent) #291 {
检查是否是系统进程的子进程。 #292 /* Check if this is a child of the system process */ #293 if (Parent != PsInitialSystemProcess) #294 { #295 /* This is a clone! */ #296 ASSERTMSG("No support for cloning yet/n",FALSE); #297 } #298 else #299 {
这是一个系统进程初始化。 #300 /* This is the initial system process */ #301 Flags &= ~PS_LARGE_PAGES; #302 Status = MmInitializeProcessAddressSpace(Process, #303 NULL, #304 NULL, #305 &Flags, #306 NULL); #307 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #308 #309 /* Create a dummy image file name */ #310 Process->SeAuditProcessCreationInfo.ImageFileName = #311 ExAllocatePoolWithTag(PagedPool, #312 sizeof(OBJECT_NAME_INFORMATION), #313 TAG('S','e','P','a')); #314 if (!Process->SeAuditProcessCreationInfo.ImageFileName) #315 { #316 /* Fail */ #317 Status = STATUS_INSUFFICIENT_RESOURCES; #318 goto CleanupWithRef; #319 } #320 #321 /* Zero it out */ #322 RtlZeroMemory(Process->SeAuditProcessCreationInfo.ImageFileName, #323 sizeof(OBJECT_NAME_INFORMATION)); #324 } #325 } #326
检查是否需要对动态连接进行映射。 #327 /* Check if we have a section object and map the system DLL */ #328 if (SectionObject) PspMapSystemDll(Process,NULL,FALSE); #329
为进程创建一个句柄。 #330 /* Create a handle for the Process */ #331 CidEntry.Object = Process; #332 CidEntry.GrantedAccess = 0; #333 Process->UniqueProcessId = ExCreateHandle(PspCidTable,&CidEntry); #334 if (!Process->UniqueProcessId) #335 { #336 /* Fail */ #337 Status = STATUS_INSUFFICIENT_RESOURCES; #338 goto CleanupWithRef; #339 } #340
设置进程的进程标识号PID。 #341 /* Set the handle table PID */ #342 Process->ObjectTable->UniqueProcessId = Process->UniqueProcessId; #343 #344 /* Check if we need to audit */ #345 if (SeDetailedAuditingWithToken(NULL)) SeAuditProcessCreate(Process); #346
检查进程是否一个工作集运行。 #347 /* Check if the parent had a job */ #348 if ((Parent) && (Parent->Job)) #349 { #350 /* FIXME: We need to insert this process */ #351 DPRINT1("Jobs not yet supported/n"); #352 ASSERT(FALSE); #353 } #354
为用户进程创建进程环境块PEB。 #355 /* Create PEB only for User-Mode Processes */ #356 if (Parent) #357 { #358 /* Create it */ #359 Status = MmCreatePeb(Process); #360 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #361 } #362
把刚创建的进程放到进程调试列表。 #363 /* The process can now be activated */ #364 KeAcquireGuardedMutex(&PspActiveProcessMutex); #365 InsertTailList(&PsActiveProcessHead,&Process->ActiveProcessLinks); #366 KeReleaseGuardedMutex(&PspActiveProcessMutex); #367
创建进程访问状态。 #368 /* Create an access state */ #369 Status = SeCreateAccessStateEx(CurrentThread, #370 ((Parent) && #371 (Parent == PsInitialSystemProcess)) ? #372 Parent : CurrentProcess, #373 &LocalAccessState, #374 &AuxData, #375 DesiredAccess, #376 &PsProcessType->TypeInfo.GenericMapping); #377 if (!NT_SUCCESS(Status)) goto CleanupWithRef; #378
把进程放入到对象目录。 #379 /* Insert the Process into the Object Directory */ #380 Status = ObInsertObject(Process, #381 AccessState, #382 DesiredAccess, #383 1, #384 NULL, #385 &hProcess); #386
删除进程访问状态。 #387 /* Free the access state */ #388 if (AccessState) SeDeleteAccessState(AccessState); #389 #390 /* Cleanup on failure */ #391 if (!NT_SUCCESS(Status)) goto Cleanup; #392
计算进程运行时间片。 #393 /* Compute Quantum and Priority */ #394 ASSERT(IsListEmpty(&Process->ThreadListHead) == TRUE); #395 Process->Pcb.BasePriority = #396 (SCHAR)PspComputeQuantumAndPriority(Process, #397 PsProcessPriorityBackground, #398 &Quantum); #399 Process->Pcb.QuantumReset = Quantum; #400
#401 /* Check if we have a parent other then the initial system process */ #402 Process->GrantedAccess = PROCESS_TERMINATE; #403 if ((Parent) && (Parent != PsInitialSystemProcess)) #404 { #405 /* Get the process's SD */ #406 Status = ObGetObjectSecurity(Process, #407 &SecurityDescriptor, #408 &SdAllocated); #409 if (!NT_SUCCESS(Status)) #410 { #411 /* We failed,close the handle and clean up */ #412 ObCloseHandle(hProcess,PreviousMode); #413 goto CleanupWithRef; #414 } #415 #416 /* Create the subject context */ #417 SubjectContext.ProcessAuditId = Process; #418 SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process); #419 SubjectContext.ClientToken = NULL; #420 #421 /* Do the access check */ #422 Result = SeAccessCheck(SecurityDescriptor, #423 &SubjectContext, #424 FALSE, #425 MAXIMUM_ALLOWED, #426 0, #427 NULL, #428 &PsProcessType->TypeInfo.GenericMapping, #429 PreviousMode, #430 &Process->GrantedAccess, #431 &AccessStatus); #432 #433 /* Dereference the token and let go the SD */ #434 ObFastDereferenceObject(&Process->Token, #435 SubjectContext.PrimaryToken); #436 ObReleaSEObjectSecurity(SecurityDescriptor,SdAllocated); #437 #438 /* Remove access if it failed */ #439 if (!Result) Process->GrantedAccess = 0; #440
设置进程访问权。 #441 /* Give the process some basic access */ #442 Process->GrantedAccess |= (PROCESS_VM_OPERATION | #443 PROCESS_VM_READ | #444 PROCESS_VM_WRITE | #445 PROCESS_QUERY_INFORMATION | #446 PROCESS_TERMINATE | #447 PROCESS_CREATE_THREAD | #448 PROCESS_DUP_HANDLE | #449 PROCESS_CREATE_PROCESS | #450 PROCESS_SET_INFORMATION | #451 STANDARD_RIGHTS_ALL | #452 PROCESS_SET_QUOTA); #453 } #454 else #455 { #456 /* Set full granted access */ #457 Process->GrantedAccess = PROCESS_ALL_ACCESS; #458 } #459
设置进程创建时间。 #460 /* Set the Creation Time */ #461 KeQuerySystemTime(&Process->CreateTime); #462
通过SEH机制来保护用户设置非法指针导致系统出错。 #463 /* Protect against bad user-mode pointer */ #464 _SEH2_TRY #465 { #466 /* Save the process handle */ #467 *ProcessHandle = hProcess; #468 } #469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) #470 { #471 /* Get the exception code */ #472 Status = _SEH2_GetExceptionCode(); #473 } #474 _SEH2_END; #475
调用进程回调函数。 #476 /* Run the Notification Routines */ #477 PspRunCreateProcessNotifyRoutines(Process,TRUE); #478
创建进程失败,要清除分配的资源。 #479 CleanupWithRef: #480 /* #481 * Dereference the process. For failures,kills the process and does #482 * cleanup present in PspDeleteProcess. For success,kills the extra #483 * reference added by ObInsertObject. #484 */ #485 ObDereferenceObject(Process); #486 #487 Cleanup: #488 /* Dereference the parent */ #489 if (Parent) ObDereferenceObject(Parent); #490 #491 /* Return status to caller */ #492 return Status; #493 } #494
通过上面的函数,就可以创建了一个系统进程,但我们知道Reactos的原理,它并不是以进程为最小的调度单位的,而是以线程为最小的调度单位,那么线程又是什么时候创建的呢? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |