到底一个线程是怎么样创建的呢?又是怎么样放到就绪队列呢?

#001  NTSTATUS

#002  NTAPI

#003  PspCreateThread(OUT PHANDLE ThreadHandle,

#004                  IN ACCESS_MASK DesiredAccess,

#005                  IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

#006                  IN HANDLE ProcessHandle,

#007                  IN PEPROCESS TargetProcess,

#008                  OUT PCLIENT_ID ClientId,

#009                  IN PCONTEXT ThreadContext,

#010                  IN PINITIAL_TEB InitialTeb,

#011                  IN BOOLEAN CreateSuspended,

#012                  IN PKSTART_ROUTINE StartRoutine OPTIONAL,

#013                  IN PVOID StartContext OPTIONAL)

#014  {

#015      HANDLE hThread;

#016      PEPROCESS Process;

#017      PETHREAD Thread;

#018      PTEB TebBase = NULL;

获取当前处理器的模式,比如内核模式、用户模式、最大模式。

#019      KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();

#020      NTSTATUS Status, AccessStatus;

#021      HANDLE_TABLE_ENTRY CidEntry;

#022      ACCESS_STATE LocalAccessState;

#023      PACCESS_STATE AccessState = &LocalAccessState;

#024      AUX_ACCESS_DATA AuxData;

#025      BOOLEAN Result, SdAllocated;

#026      PSECURITY_DESCRIPTOR SecurityDescriptor;

#027      SECURITY_SUBJECT_CONTEXT SubjectContext;

判断代码是否可以执行。

#028      PAGED_CODE();

#029      PSTRACE(PS_THREAD_DEBUG,

#030              "ThreadContext: %p TargetProcess: %p ProcessHandle: %p/n",

#031              ThreadContext, TargetProcess, ProcessHandle);

#032

当从函数PsCreateSystemThread里调用时,当前肯定是运行在内核模式,也就是通过是否有回调函数StartRoutine来判断的。

#033      /* If we were called from PsCreateSystemThread, then we're kernel mode */

#034      if (StartRoutine) PreviousMode = KernelMode;

#035

获取线程所属的进程结构。

#036      /* Reference the Process by handle or pointer, depending on what we got */

#037      if (ProcessHandle)

#038      {

通过进程句柄到对象

#039          /* Normal thread or System Thread */

#040          Status = ObReferenceObjectByHandle(ProcessHandle,

#041                                             PROCESS_CREATE_THREAD,

#042                                             PsProcessType,

#043                                             PreviousMode,

#044                                             (PVOID*)&Process,

#045                                             NULL);

#046          PSREFTRACE(Process);

#047      }

#048      else

#049      {

获取系统线程的进程对象,或者普通线程的进程有问题。

#050          /* System thread inside System Process, or Normal Thread with a bug */

#051          if (StartRoutine)

#052          {

#053              /* Reference the Process by Pointer */

#054              ObReferenceObject(TargetProcess);

#055              Process = TargetProcess;

#056              Status = STATUS_SUCCESS;

#057          }

#058          else

#059          {

#060              /* Fake ObReference returning this */

#061              Status = STATUS_INVALID_HANDLE;

#062          }

#063      }

#064

#065      /* Check for success */

#066      if (!NT_SUCCESS(Status)) return Status;

#067

如果不是内核模式,不让创建线程。

#068      /* Also make sure that User-Mode isn't trying to create a system thread */

#069      if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess))

#070      {

#071          /* Fail */

#072          ObDereferenceObject(Process);

#073          return STATUS_INVALID_HANDLE;

#074      }

#075

创建一个线程对象。

#076      /* Create Thread Object */

#077      Status = ObCreateObject(PreviousMode,

#078                              PsThreadType,

#079                              ObjectAttributes,

#080                              PreviousMode,

#081                              NULL,

#082                              sizeof(ETHREAD),

#083                              0,

#084                              0,

#085                              (PVOID*)&Thread);

#086      if (!NT_SUCCESS(Status))

#087      {

#088          /* We failed; dereference the process and exit */

#089          ObDereferenceObject(Process);

#090          return Status;

#091      }

#092

初始化线程对象。

#093      /* Zero the Object entirely */

#094      RtlZeroMemory(Thread, sizeof(ETHREAD));

#095

#096      /* Initialize rundown protection */

#097      ExInitializeRundownProtection(&Thread->RundownProtect);

#098

设置线程退出码。

#099      /* Initialize exit code */

#100      Thread->ExitStatus = STATUS_PENDING;

#101

设置线程的进程ID。

#102      /* Set the Process CID */

#103      Thread->ThreadsProcess = Process;

#104      Thread->Cid.UniqueProcess = Process->UniqueProcessId;

#105

创建线程的ID。

#106      /* Create Cid Handle */

#107      CidEntry.Object = Thread;

#108      CidEntry.GrantedAccess = 0;

#109      Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry);

#110      if (!Thread->Cid.UniqueThread)

#111      {

#112          /* We couldn't create the CID, dereference the thread and fail */

#113          ObDereferenceObject(Thread);

#114          return STATUS_INSUFFICIENT_RESOURCES;

#115      }

保存读取的族大小。

#116

#117      /* Save the read cluster size */

#118      Thread->ReadClusterSize = MmReadClusterSize;

#119

初始化LPC信号量。

#120      /* Initialize the LPC Reply Semaphore */

#121      KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1);

#122

初始化线程的列表和锁。

#123      /* Initialize the list heads and locks */

#124      InitializeListHead(&Thread->LpcReplyChain);

#125      InitializeListHead(&Thread->IrpList);

#126      InitializeListHead(&Thread->PostBlockList);

#127      InitializeListHead(&Thread->ActiveTimerListHead);

#128      KeInitializeSpinLock(&Thread->ActiveTimerListLock);

#129

#130      /* Acquire rundown protection */

#131      if (!ExAcquireRundownProtection (&Process->RundownProtect))

#132      {

#133          /* Fail */

#134          ObDereferenceObject(Thread);

#135          return STATUS_PROCESS_IS_TERMINATING;

#136      }

#137

初始化线程的TEB环境块。

#138      /* Now let the kernel initialize the context */

#139      if (ThreadContext)

#140      {

#141          /* User-mode Thread, create Teb */

#142          TebBase = MmCreateTeb(Process, &Thread->Cid, InitialTeb);

#143          if (!TebBase)

#144          {

#145              /* Failed to create the TEB. Release rundown and dereference */

#146              ExReleaseRundownProtection(&Process->RundownProtect);

#147              ObDereferenceObject(Thread);

#148              return STATUS_INSUFFICIENT_RESOURCES;

#149          }

#150

#151          /* Set the Start Addresses */

#152  #if defined(_M_IX86)

#153          Thread->StartAddress = (PVOID)ThreadContext->Eip;

#154          Thread->Win32StartAddress = (PVOID)ThreadContext->Eax;

#155  #elif defined(_M_PPC)

#156          Thread->StartAddress = (PVOID)ThreadContext->Dr0;

#157          Thread->Win32StartAddress = (PVOID)ThreadContext->Gpr3;

#158  #elif defined(_M_MIPS)

#159          Thread->StartAddress = (PVOID)ThreadContext->Psr;

#160          Thread->Win32StartAddress = (PVOID)ThreadContext->IntA0;

#161  #elif defined(_M_ARM)

#162          Thread->StartAddress = (PVOID)ThreadContext->Pc;

#163          Thread->Win32StartAddress = (PVOID)ThreadContext->R0;

#164  #elif defined(_M_AMD64)

#165          Thread->StartAddress = (PVOID)ThreadContext->Rip;

#166          Thread->Win32StartAddress = (PVOID)ThreadContext->Rax;

#167  #else

#168  #error Unknown architecture

#169  #endif

#170

#171          /* Let the kernel intialize the Thread */

#172          Status = KeInitThread(&Thread->Tcb,

#173                                NULL,

#174                                PspUserThreadStartup,

#175                                NULL,

#176                                Thread->StartAddress,

#177                                ThreadContext,

#178                                TebBase,

#179                                &Process->Pcb);

#180      }

#181      else

#182      {

创建系统线程。

#183          /* System Thread */

#184          Thread->StartAddress = StartRoutine;

#185          PspSetCrossThreadFlag(Thread, CT_SYSTEM_THREAD_BIT);

#186

#187          /* Let the kernel intialize the Thread */

#188          Status = KeInitThread(&Thread->Tcb,

#189                                NULL,

#190                                PspSystemThreadStartup,

#191                                StartRoutine,

#192                                StartContext,

#193                                NULL,

#194                                NULL,

#195                                &Process->Pcb);

#196      }

#197

初始化线程失败,就清除分配的资源。

#198      /* Check if we failed */

#199      if (!NT_SUCCESS(Status))

#200      {

#201          /* Delete the TEB if we had done */

#202          if (TebBase) MmDeleteTeb(Process, TebBase);

#203

#204          /* Release rundown and dereference */

#205          ExReleaseRundownProtection(&Process->RundownProtect);

#206          ObDereferenceObject(Thread);

#207          return Status;

#208      }

#209

检查进程是否已经删除。

#210      /* Lock the process */

#211      KeEnterCriticalRegion();

#212      ExAcquirePushLockExclusive(&Process->ProcessLock);

#213

#214      /* Make sure the proces didn't just die on us */

#215      if (Process->ProcessDelete) goto Quickie;

#216

#217      /* Check if the thread was ours, terminated and it was user mode */

#218      if ((Thread->Terminated) &&

#219          (ThreadContext) &&

#220          (Thread->ThreadsProcess == Process))

#221      {

#222          /* Cleanup, we don't want to start it up and context switch */

#223          goto Quickie;

#224      }

#225

把新创建的线程放到进程的线程列表里。

#226      /*

#227       * Insert the Thread into the Process's Thread List

#228       * Note, this is the ETHREAD Thread List. It is removed in

#229       * ps/kill.c!PspExitThread.

#230       */

#231      InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);

#232      Process->ActiveThreads++;

#233

设置启动线程。

#234      /* Start the thread */

#235      KeStartThread(&Thread->Tcb);

#236

#237      /* Release the process lock */

#238      ExReleasePushLockExclusive(&Process->ProcessLock);

#239      KeLeaveCriticalRegion();

#240

#241      /* Release rundown */

#242      ExReleaseRundownProtection(&Process->RundownProtect);

#243

#244      /* Notify WMI */

#245      //WmiTraceProcess(Process, TRUE);

#246      //WmiTraceThread(Thread, InitialTeb, TRUE);

#247

通知线程创建。

#248      /* Notify Thread Creation */

#249      PspRunCreateThreadNotifyRoutines(Thread, TRUE);

#250

#251      /* Reference ourselves as a keep-alive */

#252      ObReferenceObjectEx(Thread, 2);

#253

检查是否需要挂起线程执行。

#254      /* Suspend the Thread if we have to */

#255      if (CreateSuspended) KeSuspendThread(&Thread->Tcb);

#256

终止线程的执行。

#257      /* Check if we were already terminated */

#258      if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);

#259

#260      /* Create an access state */

#261      Status = SeCreateAccessStateEx(NULL,

#262                                     ThreadContext ?

#263                                     PsGetCurrentProcess() : Process,

#264                                     &LocalAccessState,

#265                                     &AuxData,

#266                                     DesiredAccess,

#267                                     &PsThreadType->TypeInfo.GenericMapping);

#268      if (!NT_SUCCESS(Status))

#269      {

#270          /* Access state failed, thread is dead */

#271          PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);

#272

#273          /* If we were suspended, wake it up */

#274          if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#275

#276          /* Dispatch thread */

#277          KeReadyThread(&Thread->Tcb);

#278

#279          /* Dereference completely to kill it */

#280          ObDereferenceObjectEx(Thread, 2);

#281          return Status;

#282      }

#283

把线程放到对象管理器。

#284      /* Insert the Thread into the Object Manager */

#285      Status = ObInsertObject(Thread,

#286                              AccessState,

#287                              DesiredAccess,

#288                              0,

#289                              NULL,

#290                              &hThread);

#291

#292      /* Delete the access state if we had one */

#293      if (AccessState) SeDeleteAccessState(AccessState);

#294

通过SEH机制保存线程ID和线程句柄给用户空间的变量。

#295      /* Check for success */

#296      if (NT_SUCCESS(Status))

#297      {

#298          /* Wrap in SEH to protect against bad user-mode pointers */

#299          _SEH2_TRY

#300          {

#301              /* Return Cid and Handle */

#302              if (ClientId) *ClientId = Thread->Cid;

#303              *ThreadHandle = hThread;

#304          }

#305          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)

#306          {

#307              /* Get the exception code */

#308              Status = _SEH2_GetExceptionCode();

#309

#310              /* Thread insertion failed, thread is dead */

#311              PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);

#312

#313              /* If we were suspended, wake it up */

#314              if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#315

#316              /* Dispatch thread */

#317              KeReadyThread(&Thread->Tcb);

#318

#319              /* Dereference it, leaving only the keep-alive */

#320              ObDereferenceObject(Thread);

#321

#322              /* Close its handle, killing it */

#323              ObCloseHandle(ThreadHandle, PreviousMode);

#324          }

#325          _SEH2_END;

#326          if (!NT_SUCCESS(Status)) return Status;

#327      }

#328      else

#329      {

#330          /* Thread insertion failed, thread is dead */

#331          PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);

#332

#333          /* If we were suspended, wake it up */

#334          if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#335      }

#336

获取线程创建时间。

#337      /* Get the create time */

#338      KeQuerySystemTime(&Thread->CreateTime);

#339      ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));

#340

#341      /* Make sure the thread isn't dead */

#342      if (!Thread->DeadThread)

#343      {

#344          /* Get the thread's SD */

#345          Status = ObGetObjectSecurity(Thread,

#346                                       &SecurityDescriptor,

#347                                       &SdAllocated);

#348          if (!NT_SUCCESS(Status))

#349          {

#350              /* Thread insertion failed, thread is dead */

#351              PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);

#352

#353              /* If we were suspended, wake it up */

#354              if (CreateSuspended) KeResumeThread(&Thread->Tcb);

#355

#356              /* Dispatch thread */

#357              KeReadyThread(&Thread->Tcb);

#358

#359              /* Dereference it, leaving only the keep-alive */

#360              ObDereferenceObject(Thread);

#361

#362              /* Close its handle, killing it */

#363              ObCloseHandle(ThreadHandle, PreviousMode);

#364              return Status;

#365          }

#366

设置线程安全环境变量。

#367          /* Create the subject context */

#368          SubjectContext.ProcessAuditId = Process;

#369          SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);

#370          SubjectContext.ClientToken = NULL;

#371

#372          /* Do the access check */

#373          Result = SeAccessCheck(SecurityDescriptor,

#374                                 &SubjectContext,

#375                                 FALSE,

#376                                 MAXIMUM_ALLOWED,

#377                                 0,

#378                                 NULL,

#379                                 &PsThreadType->TypeInfo.GenericMapping,

#380                                 PreviousMode,

#381                                 &Thread->GrantedAccess,

#382                                 &AccessStatus);

#383

#384          /* Dereference the token and let go the SD */

#385          ObFastDereferenceObject(&Process->Token,

#386                                  SubjectContext.PrimaryToken);

#387          ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);

#388

#389          /* Remove access if it failed */

#390          if (!Result) Process->GrantedAccess = 0;

#391

#392          /* Set least some minimum access */

#393          Thread->GrantedAccess |= (THREAD_TERMINATE |

#394                                    THREAD_SET_INFORMATION |

#395                                    THREAD_QUERY_INFORMATION);

#396      }

#397      else

#398      {

#399          /* Set the thread access mask to maximum */

#400          Thread->GrantedAccess = THREAD_ALL_ACCESS;

#401      }

#402

标记线程已经可以运行,把线程放到准备就绪队列。

#403      /* Dispatch thread */

#404      KeReadyThread(&Thread->Tcb);

#405

#406      /* Dereference it, leaving only the keep-alive */

#407      ObDereferenceObject(Thread);

#408

#409      /* Return */

#410      return Status;

#411

出错处理。

#412      /* Most annoying failure case ever, where we undo almost all manually */

#413  Quickie:

#414      /* When we get here, the process is locked, unlock it */

#415      ExReleasePushLockExclusive(&Process->ProcessLock);

#416      KeLeaveCriticalRegion();

#417

#418      /* Uninitailize it */

#419      KeUninitThread(&Thread->Tcb);

#420

#421      /* If we had a TEB, delete it */

#422      if (TebBase) MmDeleteTeb(Process, TebBase);

#423

#424      /* Release rundown protection, which we also hold */

#425      ExReleaseRundownProtection(&Process->RundownProtect);

#426

#427      /* Dereference the thread and return failure */

#428      ObDereferenceObject(Thread);

#429      return STATUS_PROCESS_IS_TERMINATING;

#430  }

通上面函数分析,已经了解一个线程创建,不但可以创建系统线程,还可以创建用户线程。当初始化线程后,就可以把线程放到调度就绪队列,准备给下一轮调试使用。

转载于:https://www.cnblogs.com/ajuanabc/archive/2009/07/12/2463815.html

reactos操作系统实现(39)相关推荐

  1. reactos操作系统实现 2

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 对于开发 ...

  2. reactos操作系统实现(2)

    对于开发一个操作系统是一个漫长的过程,并不像一个Hello world程序那么快捷,那么明了.因此对开发OS的基本知识,基本技能也需要比较高深一些,特别对一些名词和概念,更需要深入地了解.由于操作系统 ...

  3. reactos操作系统实现 1

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! reac ...

  4. reactos操作系统实现(47)

    当光盘变成记录数据以后,就开始使用光盘来分发操作系统了.毕竟光盘有着储存数据量大,成本便宜的优势.下面就来分析Reactos是怎么样通过光盘的格式来引导操作系统的. 现今的计算机BIOS,会在开机时根 ...

  5. reactos操作系统实现 3

    有人说,reactos不是实时操作系统,不能做嵌入式系统,难道真的不能做嵌入式系统吗?其实不是这样的,嵌入式系统本来就包括有两类系统,一种是要求实时性强,一种是要求实时性弱的.这两种都是嵌入式系统.因 ...

  6. reactos操作系统实现(1)

    reactos是什么操作系统呢?它是一个开源的操作系统,并且是兼容Windows XP的应用程序和驱动程序的操作系统.意思就是说,直接安装一个reactos之后,把第三方的驱动程序安装好后,就可以运行 ...

  7. reactos操作系统实现(3)

    有人说,reactos不是实时操作系统,不能做嵌入式系统,难道真的不能做嵌入式系统吗?其实不是这样的,嵌入式系统本来就包括有两类系统,一种是要求实时性强,一种是要求实时性弱的.这两种都是嵌入式系统.因 ...

  8. reactos操作系统实现(12)

    有了上面的知识,就来分析ReactOS里引导任务是怎么样设置全局描述符表.其工作过程如下图所示: 由于CPU初始化运行后,就当作为一个任务在运行.这里主要设置这个任务的运行保存环境,以便CPU可以交给 ...

  9. reactos操作系统实现(6)

    硬盘引导的流程与相应源码文件名称: 引导序号 引导过程 引导执行代码位数 目标文件名称 1. 主引导代码(Master Boot Record (MBR) code),主要寻找活动分区,然后读入引导扇 ...

最新文章

  1. gif 图片制作和拆解
  2. 系统开出出现问题~~~\WINDOWS\SYSTEM32\CONFIG\SYSTEM 损坏或丢失无法开机
  3. 简单的石头剪刀布(机器胜率略高)
  4. IOS 多线程04-GCD详解 底层并发 API
  5. java对接支付宝微信银联_经典设计模式之策略模式【如何重构聚合支付平台,对接【支付宝,微信,银联支付】】(示例代码)...
  6. vscode extension
  7. python打包后怎么安装_别再问我怎么Python打包成exe了!
  8. java多线程下如何调用一个共同的内存单元(调用同一个对象)
  9. zookeeper中ExpiryQueue详解
  10. matlab数组的创建
  11. 关于C2100间接寻址的问题
  12. 无惧失败,做一只逆流而上的鱼
  13. spring boot儿童教育管理系统毕业设计源码281442
  14. Pycharm下载pytorch
  15. h5棋牌游戏源码 java_YM202H5房ka微信贝密棋盘游戏平台,完整全套游戏源码下载...
  16. 钛资本研究院:企业服务早期投资方法论
  17. Markdown写出高大上时序图
  18. oracle数据结构体
  19. Arduino Uno 蜂鸣器播放《天空之城》
  20. python小课文件_Python--小甲鱼学习笔记--第28课:文件(文件打开方式、文件对象方法)...

热门文章

  1. GG32F450XX上移植RT-Thread+LWIP协议栈
  2. 笔记存储仓库神器->印象笔记的使用方法
  3. 酷派s6、Coolpad 9190l_C00 无log信息输出解决方法
  4. Android接入高德地图SDK 一引入高德sdk
  5. EIP-3523:半同质代币介绍
  6. 茶颜悦色的“雷”早已埋下
  7. win10禁用USB恢复USB
  8. 使用BP网络逼近函数-matlab
  9. 多传感器融合的SLAM综述
  10. [机缘参悟-33]:眼见不一定为实,大多数时候“眼见为虚”