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的原理,它并不是以进程为最小的调度单位的,而是以线程为最小的调度单位,那么线程又是什么时候创建的呢?

相关文章

一、前言 在组件方面react和Vue一样的,核心思想玩的就是组件...
前言: 前段时间学习完react后,刚好就接到公司一个react项目...
前言: 最近收到组长通知我们项目组后面新开的项目准备统一技...
react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...