reactos操作系统实现(37)

时间:2021-03-12 05:38:28

下面来继续分析创建进程函数,过程如下:

保存工作集数据。

#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 rundownprotection */

#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 ErrorProcessing */

#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)) gotoCleanupWithRef;

#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 theprocess rundown */

#137              if(ExAcquireRundownProtection(&Process->RundownProtect))

#138              {

#139                  /* If the parent has asection, 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 sectionobject */

#148              if (!SectionObject)

#149              {

#150                  /* Then the process is intermination, 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)) gotoCleanupWithRef;

#171 

#172          /* Save the debug object */

#173          Process->DebugPort = DebugObject;

#174 

#175          /* Check if the caller doesn't wantthe 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 hisdebug 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)) gotoCleanupWithRef;

#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 processbeing built */

#211      if (Parent)

#212      {

 

如果有父进程,就创建子进程空间。

#213          /* Create the address space for thechild */

#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 bootprocess, we're already semi-initialized */

#226          Process->ObjectTable =CurrentProcess->ObjectTable;

#227          Status =MmInitializeHandBuiltProcess(Process, DirectoryTableBase);

#228          if (!NT_SUCCESS(Status)) gotoCleanupWithRef;

#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)) gotoCleanupWithRef;

#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 theprocess */

#263          Status = ObInitProcess(Flags &PS_INHERIT_HANDLES ? Parent : NULL,

#264                                 Process);

#265          if (!NT_SUCCESS(Status)) gotoCleanupWithRef;

#266      }

#267      else

#268      {

#269          /* Do the second part of the bootprocess memory setup */

#270          Status =MmInitializeHandBuiltProcess2(Process);

#271          if (!NT_SUCCESS(Status)) gotoCleanupWithRef;

#272      }

#273 

 

到这里已经创建进程成功了。

#274      /* Set success for now */

#275      Status = STATUS_SUCCESS;

#276 

 

检查是否用户模式进程。

#277      /* Check if this is a real user-modeprocess */

#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)) gotoCleanupWithRef;

#289      }

#290      else if (Parent)

#291      {

 

检查是否是系统进程的子进程。

#292          /* Check if this is a child of thesystem process */

#293          if (Parent != PsInitialSystemProcess)

#294          {

#295              /* This is a clone! */

#296              ASSERTMSG("No support forcloning yet/n", FALSE);

#297          }

#298          else

#299          {

 

这是一个系统进程初始化。

#300              /* This is the initial systemprocess */

#301              Flags &= ~PS_LARGE_PAGES;

#302              Status =MmInitializeProcessAddressSpace(Process,

#303                                                      NULL,

#304                                                      NULL,

#305                                                      &Flags,

#306                                                      NULL);

#307              if (!NT_SUCCESS(Status)) gotoCleanupWithRef;

#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 andmap 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 thisprocess */

#351          DPRINT1("Jobs not yetsupported/n");

#352          ASSERT(FALSE);

#353      }

#354 

 

为用户进程创建进程环境块PEB

#355      /* Create PEB only for User-ModeProcesses */

#356      if (Parent)

#357      {

#358          /* Create it */

#359          Status = MmCreatePeb(Process);

#360          if (!NT_SUCCESS(Status)) gotoCleanupWithRef;

#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)) gotoCleanupWithRef;

#378 

 

把进程放入到对象目录。

#379      /* Insert the Process into the ObjectDirectory */

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