reactos操作系统实现(20)

时间:2021-09-02 04:49:37
下面来了解内核执行体的处理,它是在初始化内核线程后运行的,代码如下:

#001   /* Setup the Idle Thread */

#002      KeInitializeThread(InitProcess,

#003                         InitThread,

#004                         NULL,

#005                         NULL,

#006                         NULL,

#007                         NULL,

#008                         NULL,

#009                         IdleStack);

......

#033 

#034      /* Set up the thread-related fields inthe PRCB */

#035      Prcb->CurrentThread = InitThread;

#036      Prcb->NextThread = NULL;

#037      Prcb->IdleThread = InitThread;

#038 

#039      /* Initialize the Kernel Executive */

#040      ExpInitializeExecutive(Number,LoaderBlock);

上面这句就是调用函数ExpInitializeExecutive来初始化内核执行体的功能,它是内核所有功能管理初始化,比如内核对象管理器,内核内存管理,还有硬件抽象层HAL的初始化。具体的部分代码如下:

#001  VOID

#002  NTAPI

#003  ExpInitializeExecutive(IN ULONG Cpu,

#004                         IN PLOADER_PARAMETER_BLOCK LoaderBlock)

#005  {

#006      PNLS_DATA_BLOCK NlsData;

#007      CHAR Buffer[256];

#008      ANSI_STRING AnsiPath;

#009      NTSTATUS Status;

#010      PCHAR CommandLine, PerfMem;

#011      ULONG PerfMemUsed;

#012      PLDR_DATA_TABLE_ENTRY NtosEntry;

#013      PRTL_MESSAGE_RESOURCE_ENTRY MsgEntry;

#014      ANSI_STRING CsdString;

#015      ULONG Remaining = 0;

#016      PCHAR RcEnd = NULL;

#017      CHAR VersionBuffer [65];

#018 

#019      /* Validate Loader */

#020      if (!ExpIsLoaderValid(LoaderBlock))

#021      {

#022          /* Invalid loader version */

#023          KeBugCheckEx(MISMATCHED_HAL,

#024                       3,

#025                       LoaderBlock->Extension->Size,

#026                      LoaderBlock->Extension->MajorVersion,

#027                      LoaderBlock->Extension->MinorVersion);

#028      }

 

上面主要检查引导参数是否正确,如果不正确就进入处理出错,直接停在出错位置上,把出错码输出。

 

#029 

#030      /* Initialize PRCB pool lookasidepointers */

#031      ExInitPoolLookasidePointers();

上面是初始化PRCB里的后备列表缓冲区指针,那么什么是后备列表呢?堆管理器管理着系统和用户的堆内存,它把堆空间分为相同尺寸的块(block)。堆管理器会根据堆分配请求,去选择一个合适尺寸的未使用的块。显然,这个过程需要点时间。如果你需要固定尺寸的内存块,但是你事先并不知道它的大小和使用频率,这样的话为了性能的原因,你还是使用后备列表(Lookaside Lists)的,后备列表是只有内核模式才有的。

    后备列表和系统内存池的主要的区别是什么呢?后备列表只可以分配固定大小的事先定义尺寸的内存块。后备列表会快很多,因为它不需要去搜索可用的未分配的内存。

    当你刚接触后备列表,你需要解决的问题不是怎么创建后备列表,而是管理你要分配的内存块。

        后备列表(lookaside list)是一组事先分配的相同尺寸的内存块。这些块有些在使用,有些没被使用。当有内存分配请求的时候,系统会遍历这个列表寻找最近的未分配的块。如果未分配的块找到了,分配请求就很快被满足了。否则系统必须从分页或不分页内存池去分配。根据列表中分配行为发生的频率,系统会自动调整未分配块的数量来满足分配请求,分配的频率越高,会有越多的块被存储在后备列表中。后备列表如果总是不被使用,也会自动减少空间大小。

其实后备列表就是保存一些最近使用的空闲内存的内存块。