下面来继续分析创建进程函数,过程如下:
保存工作集数据。
#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项目致力于为大家开发一个免费而且完全兼容 Microsoft Windows XP 的操作系统。ReactOS 旨在通过使用类似构架和提供完整公共接口实现与 NT 以及 XP 操作系统二进制下的应用程序和驱动设备的完全兼容。 ...
本书通过分析ReactOS的源代码介绍了Windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有ReactOS的源代码(以及...
本书通过分析ReactOS的源代码介绍了Windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有ReactOS的源代码(以及...
JS操作系统 Web上的统一操作系统。 使用的技术: HTML CSS JavaScript React-JS 如何在本地运行: 克隆仓库git clone https://github.com/NJACKWinterOfCode/JS-OS.git 进入JS-OS光盘进入JS-OS cd JS-OS 安装...
漫谈兼容内核之一:ReactOS怎样实现系统调用 漫谈兼容内核之二:关于kernel-win32的对象管理 漫谈兼容内核之三:Kernel-win32的文件操作 漫谈兼容内核之四:Kernel-win32的进程管理 漫谈兼容内核之五:Kernel-win32...
在本文档中,我们以Windows NT和ReactOS提供的Fibers实现为参考,介绍了可加载内核模块(LKM)实现。 虽然用户空间实现通常因其开销少且易于调试而成为首选,但是内核空间实现允许更深入地了解内核子系统的工作方式...
01:ReactOS怎样实现系统调用.pdf 02:关于kernel -win32的对象管理.pdf 03:关于kernel-win32的文件操作.pdf 04:Kernel-win32的进程管理.pdf 05:Kernel-win32的系统调用机制.pdf 06:二进制映像的类型识别.pdf 07...
React式对象实现。 结帐 用法 var obj = new ReactiveObject ( { 'foo' : '1' } ) ; obj . defineProperty ( 'bar' , 2 ) ; obj . foo = '2' ; obj . undefineProperty ( 'foo' ) ; // Don't use 'delete obj.foo' ...
远线程注入 每个进程都有自己的虚拟地址空间,对32位进程来说,这个地址空间的大小为4GB。...如下摘自ReactOS 3.14的代码所示,CreateRemoteThread实际实现的功能就是调用NtCreateThread创建一个属于目标进程的线程。
漫谈兼容内核之一:ReactOS怎样实现系统调用 漫谈兼容内核之二:关于kernel-win32的对象管理 漫谈兼容内核之三:Kernel-win32的文件操作 漫谈兼容内核之四:Kernel-win32的进程管理 漫谈兼容内核之五:Kernel-win32...
艺术家,专辑和曲目都以文件和文件夹的形式呈现,并且可以在Winamp重新实现轻松地进行操作和播放。现场环境动机构建软件应该保持乐趣。 这个项目主要是一个沙箱,我可以尝试并提高对React和TypeScript的了解。 这也...
isIpad() 设备型号为 iPad Device.isIphone() 设备型号为 iPhone Properties Device.model 设备型号,如 iPhone 或 iPad Device.deviceName 设备名称,如 John Smith 的 iPhone Device.systemName设备操作系统名称...
内存转储是通过使用NTFS事务完成的,NTFS事务使我们可以将转储写入内存,并且MiniDumpWriteDump API已被ReactOS的MiniDumpWriteDump实现改编所取代。 然后,BOF使用base64对内存中的数据进行编码,将其分块,然后...
谈兼容内核之一:ReactOS怎样实现系统调用.pdf 漫谈兼容内核之二:关于kernel -win32的对象管理.pdf 漫谈兼容内核之三:关于kernel-win32的文件操作.pdf 漫谈兼容内核之四:Kernel-win32的进程管理.pdf 漫谈兼容内核...
在许多情况下,操作员习惯于处理遥测,实时图表,警报等,这可以帮助他们确定有问题的机器并做出React以解决任何潜在的问题。 但是,一个问题浮现在脑海:如果机器可以自动调整自身并为用户提供自我修复功能,那...
功能,主题,UI / API文本,错误消息,命令内置支持: Arista EOS 鸟思科IOS-XR 思科IOS / IOS-XE 思科NX-OS FRRouting 了华为瞻博JunOS 米克罗蒂克诺基亚SR OS TNSR 虚拟操作系统对任何其他配置支持(可选)通过SSH...
xe-crawlerxe-crawler 是遵循声明式、可监测理念的分布式爬虫,其计划提供 Node.js、Go、Python 多种实现,能够对于静态 Web 页面、动态 Web 页面、关系型数据库、操作系统等异构多源数据进行抓取。xe-crawler 希望...
实现分块功能可以采用手动循环的对每个块依次操作,也可以使用Matlab提供的分块处理功能blkproc。 选择两张大小相同的图像,分别进行DFT变换后,置换两幅图像的幅度和相位信息后再作反变换,观察并分析结果。 主要...