操作系统专题提供操作系统的最新资讯内容,帮你更好的了解操作系统。
 下面接着来分析EiAllocatePool函数,这个函数要传入使用者内存类型、内存大小、内存标记和调用者地址。 #001  static PVOID NTAPI #002  EiAllocatePool(POOL_TYPE PoolType, #003                 ULONG NumberOfBytes, #004                 ULONG Tag, #00
 在内存管理里,绝大部份内存都是分页内存。分页内存就是把内存分成4K页大小的内存块,这些内存块不但可以在物理内存里,也可以切换时保存到硬盘里。这些内存管理里是通过下面的代码进行的,如下: #001  VOID #002  INIT_FUNCTION #003  NTAPI #004  MmInitializePagedPool(VOID) #005  { #006       /* #007   
 内存大小好像永远追不上人们的需求,以前以为512K就很大了,到现在内存已经是4G,8G内存了,但还是不能满足人们的需求。因为目前的系统都是多进程运行,每个进程都需要占用4G的内存,那么10个进程,就占用相当可观的内存了。这时就需要把进程不经常使用的内存数据切换到硬盘里,需要时再换回来。如果一个进程的内存已经换到硬盘上,而这个进程又想访问那些在硬盘的内存数据时,就会产生一个缺页中断。这个中断是CP
 对无效页面的一次访问称为“缺页错误”。对于这类错误都会导致中断处理函数MmAccessFault。那么什么样的情况才叫做无效页面呢?主要有下面几种情况: l         所有访问的页面不存内存里,而是磁盘里。 l         访问的页面在后备列表里。 l         访问的页面没有提交写操作。 l         从用户态访问核心态的页面。 l         对只读页面产生写操作。
 下面来分析保存数据时缺页中断函数,它的代码如下: #001  NTSTATUS #002  NTAPI #003  MmpAccessFault(KPROCESSOR_MODE Mode, #004                    ULONG_PTR Address, #005                    BOOLEAN FromMdl) #006  { #007     PMM
这个函数主要功能就是实现访问不存在的页面。 #001  NTSTATUS #002  NTAPI #003  MmNotPresentFault(KPROCESSOR_MODE Mode, #004                             ULONG_PTR Address, #005                             BOOLEAN FromMdl) #00
当Reactos在系统初始化时,就会调用进程管理初始化函数PsInitSystem来进行初始化。只有把进程管理初始化后,才可以创建进程,这样才可运行各种各样的任务。下面就来分析进程管理器初始化函数: #001  BOOLEAN #002  NTAPI #003  PsInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock) #004  { 在参数里把系统
现在就来分析第一阶段的进程管理器初始化函数PspInitPhase0,如下: #001  BOOLEAN #002  NTAPI #003  PspInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) #004  { #005      NTSTATUS Status; #006      OBJECT_ATTRIBUTES ObjectAttrib
初始化活动的进程列表。 #076      /* Initialize the Active Process List */ #077      InitializeListHead(&PsActiveProcessHead); #078      KeInitializeGuardedMutex(&PspActiveProcessMutex); #079    获取空闲的进程列表。在Reacto
前面分析了进程管理器的初始化工作,主要就是把进程管理器的列表、对象初始化,还有第一和第二阶段的初始化工作。接着下来,我们来分析一下进程创建函数,看看进程在Reactos里是怎么样创建的,需要调用什么函数来创建进程,还有应用程序是怎么样调用API函数来创建进程的。 可以从前面分析的代码里,看到创建第二个进程代码如下: #196      Status = PsCreateSystemThread(&
下面来继续分析创建进程函数,过程如下: 保存工作集数据。 #070      /* Save working set data */ #071      MinWs = PsMinimumWorkingSet; #072      MaxWs = PsMaximumWorkingSet; #073    创建一个进程对象。 #074      /* Create the Object */ #07
由于Reactos是以线程为最小的调度单位,如果仅仅创建进程的数据结构,不足以运行进程的任务,每个进程至少需要一个线程才可以运行,下面就来分析系统进程的线程创建,代码如下: #195      /* Setup the system initialization thread */ #196      Status = PsCreateSystemThread(&SysThreadHandle,
到底一个线程是怎么样创建的呢?又是怎么样放到就绪队列呢? #001  NTSTATUS #002  NTAPI #003  PspCreateThread(OUT PHANDLE ThreadHandle, #004                  IN ACCESS_MASK DesiredAccess, #005                  IN POBJECT_ATTRIBUTES
  由于Reactos的调度单位是线程,所以它的状态机就是基于线程的。比如进程A有5个线程,进程B有2个线程,总共就是12个线程来进行调度,也就是把CPU的时间分成12等份。线程总共状态如下: #001  // #002  // Thread States #003  // #004  typedef enum _KTHREAD_STATE #005  { #006      Initialize
当线程初始化成功后,是怎么样放到推迟就绪队列的呢?通过下面这几个函数的分析,就会了解这个问题了。从以前的分析可以知道是调用函数KeReadyThread来执行的,这个函数的代码如下: #001  VOID #002  NTAPI #003  KeReadyThread(IN PKTHREAD Thread) #004  { 这里参数Thread就是刚刚创建的线程。   #005      KIRQ
接着下来,就需要分析函数KiReadyThread的作用了。根据线程状态来判断是否可以放入延迟队列,还是设置它为转换状态,代码如下: #001  VOID #002  NTAPI #003  KiReadyThread(IN PKTHREAD Thread) #004  {   获取当前线程的进程对象。 #005      IN PKPROCESS Process = Thread->ApcSta
前面介绍放到延迟队列是单核的版本,下面来学习多核的版本,代码如下: #001  // #002  // This routine makes the thread deferred ready on the boot CPU. #003  // #004  FORCEINLINE #005  VOID #006  KiInsertDeferredReadyList(IN PKTHREAD Thre
前面分析了怎么样把一个线程放到延迟就绪队列,接着下来的问题就是这些在就绪队列里的线程什么时候开始运行呢?又是怎么样把就绪队列的线程取出来运行的呢?线程调度的触发事件有以下四种: 1) 线程进入就绪状态,如一个刚创建的线程,或者一个刚结束的线程。 2) 线程的时间片用完。 3) 线程调用系统服务发生等待,或者被系统改变其优先级。 4) 线程改变自己运行的处理器。   先来分析第一种情况,当线程结束时
怎么样从一个延迟就绪队列里选择合适的线程运行呢?下面就来分析这段代码,如下: #001  // #002  // This routine scans for an appropriate ready thread to select at the #003  // given priority and for the given CPU. #004  // #005  FORCEINLINE #
在线程调度里可以看到,需要调用函数KiSwapContext来进行运行环境切换,由于每个CPU都是只能运行一个线程,而多个线程在运行过程中被中断了,那么就需要保存CPU所有寄存器,以便下一次恢复线程时可以接续运行。现在就来分析这个函数是怎么样实现这些工作的,代码如下: #001  /*++ #002   * KiSwapContext #003   * #004   *     The KiSwa