初窥Windows内核——学习Windows Research Kernel手记(三)

STEP 2——记录/恢复线程运行上下文

    首先说明一下什么是“陷阱帧”。当一个在用户模式执行的线程请求一个系统调用,在x86平台上,也就是一条INT指令,或者sysenter指令,随即就会通过一个软件中断陷入的到内核。这时CPU的工作状态由之前的用户态切换到内核态(也就是驱动开发中常说的ring3ring0)。在这个切换过程中,系统要做一些前期的工作。因为系统服务例程是占用调用者线程的上下文来执行的,所以有必要保存调用者被中断时的状态,以便系统服务例程结束后,调用者可以继续运行。由于一个线程有两个栈,一个是用户模式栈,一个是内核模式栈,在用户态使用的是用户栈,在内核态使用的是内核栈,所以陷入到内核时并不需要保存用户栈的内容,需要保存的仅仅是一些寄存器的状态。这就是线程的“硬件上下文”。为此,操作系统定了一个名为_KTRAP_FRAME的结构体,这个结构体就代表了“硬件上下文”,也就是所谓的“陷阱帧”。_KTRAP_FRMAE定义如下:

typedef struct _KTRAP_FRAME {

//

//  Following 4 values are only used and defined for DBG systems,

//  but are always allocated to make switching from DBG to non-DBG

//  and back quicker.  They are not DEVL because they have a non-0

//  performance impact.

//

    ULONG   DbgEbp;         // Copy of User EBP set up so KB will work.

    ULONG   DbgEip;         // EIP of caller to system call, again, for KB.

    ULONG   DbgArgMark;     // Marker to show no args here.

    ULONG   DbgArgPointer;  // Pointer to the actual args

//

//  Temporary values used when frames are edited.

//

//

//  NOTE:   Any code that want's ESP must materialize it, since it

//          is not stored in the frame for kernel mode callers.

//

//          And code that sets ESP in a KERNEL mode frame, must put

//          the new value in TempEsp, make sure that TempSegCs holds

//          the real SegCs value, and put a special marker value into SegCs.

//

 

    ULONG   TempSegCs;

    ULONG   TempEsp;

 

//

//  Debug registers.

//

 

    ULONG   Dr0;

    ULONG   Dr1;

    ULONG   Dr2;

    ULONG   Dr3;

    ULONG   Dr6;

    ULONG   Dr7;

 

//

//  Segment registers

//

 

    ULONG   SegGs;

    ULONG   SegEs;

    ULONG   SegDs;

 

//

//  Volatile registers

//

 

    ULONG   Edx;

    ULONG   Ecx;

    ULONG   Eax;

 

//

//  Nesting state, not part of context record

//

 

    ULONG   PreviousPreviousMode;

 

    PEXCEPTION_REGISTRATION_RECORD ExceptionList;

                                            // Trash if caller was user mode.

                                            // Saved exception list if caller

                                            // was kernel mode or we're in

                                            // an interrupt.

 

//

//  FS is TIB/PCR pointer, is here to make save sequence easy

//

    ULONG   SegFs;

//

//  Non-volatile registers

//

    ULONG   Edi;

    ULONG   Esi;

    ULONG   Ebx;

    ULONG   Ebp;

 

//

//  Control registers

//

    ULONG   ErrCode;

    ULONG   Eip;

    ULONG   SegCs;

    ULONG   EFlags;

 

    ULONG   HardwareEsp;    // WARNING - segSS:esp are only here for stacks

    ULONG   HardwareSegSs;  // that involve a ring transition.

 

    ULONG   V86Es;          // these will be present for all transitions from

    ULONG   V86Ds;          // V86 mode

    ULONG   V86Fs;

    ULONG   V86Gs;

} KTRAP_FRAME;

    在陷入内核时,系统首先会在内核栈的栈底建立一个“陷阱帧”,等到系统调用的结束返回时,再根据陷阱帧中记录的内容,设置好寄存器状态,使得用户线程继续运行。

要明确的一点是,我们的系统调用也是系统调用,其执行过程和一般的系统调用没有任何区别。所以,当我们的这系统调用执行时,“陷阱帧”已经被系统创建好了。当系统调用结束时,系统自己就会根据“陷阱帧”的内容设置好寄存器状态。这些完全不用我们来操心。我们仅仅需要把“陷阱帧”记录下来,替换回去,这样就能达到目的了。

    这里我先把我的这个系统调用的代码列出来:

NTSTATUS

NtRecordOrRecoveryTrapFrame( )

{

    ULONG nByte;

    PKTHREAD CurrentThread;

    NTSTATUS    ntStatus = STATUS_SUCCESS;

    UNICODE_STRING   szPath;

    IO_STATUS_BLOCK   IoStatusBlock;

    HANDLE     FileHandle= 0;

    PKTRAP_FRAME TrapFrame;

    PVOID Reader;

   

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值