`
yuanjinxiu
  • 浏览: 659099 次
文章分类
社区版块
存档分类
最新评论

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

分享到:
评论

相关推荐

    ReactOS-0.4.13-release-14-g2494cfc-iso.zip

    ReactOS项目致力于为大家开发一个免费而且完全兼容 Microsoft Windows XP 的操作系统。ReactOS 旨在通过使用类似构架和提供完整公共接口实现与 NT 以及 XP 操作系统二进制下的应用程序和驱动设备的完全兼容。 ...

    Windows 内核情景分析--采用开源代码ReactOS (上册) part02

    本书通过分析ReactOS的源代码介绍了Windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有ReactOS的源代码(以及...

    Windows 内核情景分析--采用开源代码ReactOS (上册) part01

    本书通过分析ReactOS的源代码介绍了Windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有ReactOS的源代码(以及...

    JS-OS:Web上的统一操作系统

    JS操作系统 Web上的统一操作系统。 使用的技术: HTML CSS JavaScript React-JS 如何在本地运行: 克隆仓库git clone https://github.com/NJACKWinterOfCode/JS-OS.git 进入JS-OS光盘进入JS-OS cd JS-OS 安装...

    漫谈兼容内核.zip

    漫谈兼容内核之一:ReactOS怎样实现系统调用 漫谈兼容内核之二:关于kernel-win32的对象管理 漫谈兼容内核之三:Kernel-win32的文件操作 漫谈兼容内核之四:Kernel-win32的进程管理 漫谈兼容内核之五:Kernel-win32...

    LKM-光纤:高级操作系统和虚拟化项目(20172018)课程在罗马大学萨皮恩扎市举行

    在本文档中,我们以Windows NT和ReactOS提供的Fibers实现为参考,介绍了可加载内核模块(LKM)实现。 虽然用户空间实现通常因其开销少且易于调试而成为首选,但是内核空间实现允许更深入地了解内核子系统的工作方式...

    漫谈Linux兼容内核

    01:ReactOS怎样实现系统调用.pdf 02:关于kernel -win32的对象管理.pdf 03:关于kernel-win32的文件操作.pdf 04:Kernel-win32的进程管理.pdf 05:Kernel-win32的系统调用机制.pdf 06:二进制映像的类型识别.pdf 07...

    harmonyos2-reactive-extra:流星React额外包

    React式对象实现。 结帐 用法 var obj = new ReactiveObject ( { 'foo' : '1' } ) ; obj . defineProperty ( 'bar' , 2 ) ; obj . foo = '2' ; obj . undefineProperty ( 'foo' ) ; // Don't use 'delete obj.foo' ...

    DLL注入之远线程方式

    远线程注入 每个进程都有自己的虚拟地址空间,对32位进程来说,这个地址空间的大小为4GB。...如下摘自ReactOS 3.14的代码所示,CreateRemoteThread实际实现的功能就是调用NtCreateThread创建一个属于目标进程的线程。

    Windows之漫谈兼容内核

    漫谈兼容内核之一:ReactOS怎样实现系统调用 漫谈兼容内核之二:关于kernel-win32的对象管理 漫谈兼容内核之三:Kernel-win32的文件操作 漫谈兼容内核之四:Kernel-win32的进程管理 漫谈兼容内核之五:Kernel-win32...

    winampify::high_voltage:具有操作系统外观的界面和经典音频播放器Winamp的重新实现的Spotify Web客户端

    艺术家,专辑和曲目都以文件和文件夹的形式呈现,并且可以在Winamp重新实现轻松地进行操作和播放。现场环境动机构建软件应该保持乐趣。 这个项目主要是一个沙箱,我可以尝试并提高对React和TypeScript的了解。 这也...

    React Native 的 UIDevice 类包装器

    isIpad() 设备型号为 iPad Device.isIphone() 设备型号为 iPhone Properties Device.model 设备型号,如 iPhone 或 iPad Device.deviceName 设备名称,如 John Smith 的 iPhone Device.systemName设备操作系统名称...

    CredBandit

    内存转储是通过使用NTFS事务完成的,NTFS事务使我们可以将转储写入内存,并且MiniDumpWriteDump API已被ReactOS的MiniDumpWriteDump实现改编所取代。 然后,BOF使用base64对内存中的数据进行编码,将其分块,然后...

    漫谈兼容内核.7z

    谈兼容内核之一:ReactOS怎样实现系统调用.pdf 漫谈兼容内核之二:关于kernel -win32的对象管理.pdf 漫谈兼容内核之三:关于kernel-win32的文件操作.pdf 漫谈兼容内核之四:Kernel-win32的进程管理.pdf 漫谈兼容内核...

    phoebe:菲比

    在许多情况下,操作员习惯于处理遥测,实时图表,警报等,这可以帮助他们确定有问题的机器并做出React以解决任何潜在的问题。 但是,一个问题浮现在脑海:如果机器可以自动调整自身并为用户提供自我修复功能,那...

    hyperglass:超级玻璃是试图使互联网变得更好的网络外观玻璃

    功能,主题,UI / API文本,错误消息,命令内置支持: Arista EOS 鸟思科IOS-XR 思科IOS / IOS-XE 思科NX-OS FRRouting 了华为瞻博JunOS 米克罗蒂克诺基亚SR OS TNSR 虚拟操作系统对任何其他配置支持(可选)通过SSH...

    sentinel-crawler:Xenomorph Crawler, a Concise, Declarative and Observable Distributed Crawler(Node Go Java Rust) For Web, RDB, OS, also can act as a Monitor(with Prometheus) or ETL for Infrastructure 多语言执行器,分布式爬虫

    xe-crawlerxe-crawler 是遵循声明式、可监测理念的分布式爬虫,其计划提供 Node.js、Go、Python 多种实现,能够对于静态 Web 页面、动态 Web 页面、关系型数据库、操作系统等异构多源数据进行抓取。xe-crawler 希望...

    图像dct变换matlab代码-SJTU-IE307-hw1:ConductedbyProf.XieRong

    实现分块功能可以采用手动循环的对每个块依次操作,也可以使用Matlab提供的分块处理功能blkproc。 选择两张大小相同的图像,分别进行DFT变换后,置换两幅图像的幅度和相位信息后再作反变换,观察并分析结果。 主要...

Global site tag (gtag.js) - Google Analytics