windows线程Context

线程;操作系统会维护该线程的CPU寄存器的状态,该结构为上下文结构。Context

线程创建时可以指定线程为暂停状态,这样操作系统在调度时便不会进行调度该线程。

当线程的运行坏境作出修改时,必须是线程成为可调度进程。ResumeThread如果该函数运行成功返回线程的前一个暂停计数。

 

每个线程内核对象都维护着一个CONTEXT结构,里面保存了线程运行的状态,线程也就是eip。

使得CPU可以记得上次运行该线程运行到哪里了,该从哪里开始运行,该线程内部数据如何如何。

该结构是与CPU有关的,特定的CPU对应着特定的CONTEXT结构。

x86类型CPU对应的CONTEXT结构文档如下:

typedef struct _CONTEXT {

    // The flag values within this flag control the contents of

    // a CONTEXT record.

    //

    // If the context record is used as an input parameter, then

    // for each portion of the context record controlled by a flag

    // whose value is set, it is assumed that that portion of the

    // context record contains valid context. If the context record

    // is being used to modify a thread's context, only that

    // portion of the thread's context will be modified.

    //

    // If the context record is used as an IN OUT parameter to capture

    // the context of a thread, only those portions of the thread's

    // context corresponding to set flags will be returned.

    //

    // The context record is never used as an OUT only parameter.

    //

 

    DWORD ContextFlags;

 

    //

    // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is

    // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT

    // included in CONTEXT_FULL.

 

    DWORD   Dr0;

    DWORD   Dr1;

    DWORD   Dr2;

    DWORD   Dr3;

    DWORD   Dr6;

    DWORD   Dr7;

 

    // This section is specified/returned if the

    // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.

 

    FLOATING_SAVE_AREA FloatSave;

 

    // This section is specified/returned if the

    // ContextFlags word contains the flag CONTEXT_SEGMENTS.

    //

 

    DWORD   SegGs;

    DWORD   SegFs;

    DWORD   SegEs;

    DWORD   SegDs;

 

    //

    // This section is specified/returned if the

    // ContextFlags word contains the flag CONTEXT_INTEGER.

 

    DWORD   Edi;

    DWORD   Esi;

    DWORD   Ebx;

    DWORD   Edx;

    DWORD   Ecx;

    DWORD   Eax;

 

    // This section is specified/returned if the

    // ContextFlags word contains the flag CONTEXT_CONTROL.

 

    DWORD   Ebp;

    DWORD   Eip;

    DWORD   SegCs;              // MUST BE SANITIZED

    DWORD   EFlags;             // MUST BE SANITIZED

    DWORD   Esp;

    DWORD   SegSs;

 

    //

    // This section is specified/returned if the ContextFlags word

    // contains the flag CONTEXT_EXTENDED_REGISTERS.

    // The format and contexts are processor specific

 

    BYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];

 

} CONTEXT;

可见,该CONTEXT结构中,保存着直接和CPU有关的信息:

 

1、ContextFlags,在查询的时候需要设置该字段,表示查询哪些其他的CONTEXT结构字段。

2、调试寄存器组

3、FLOATING_SAVE_AREA FloatSave —— 浮点寄存器

4、段寄存器

5、通用数据寄存器(整型寄存器)组

6、控制寄存器组——比如CS、BP、SP之类的保存基址指针和堆栈指针、程序计数器。

7、BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION] —— 扩展寄存器组

 

可以查询CONTEXT结构中的内容。如上所述,通过设置CONTEXT中的ContextFlags字段,选择要查询的内容:

 

1、CONTEXT_DEBUG_REGISTERS,查询调式寄存器

2、CONTEXT_FLOATING_POINT,查询浮点寄存器

3、CONTEXT_SEGMENTS,查询段寄存器

4、CONTEXT_INTEGER,查询通用数据寄存器

5、CONTEXT_CONTROL,查询控制寄存器组

6、CONTEXT_EXTENDED_REGISTERS,扩展寄存器组

 

在查询之前,先调用SuspendThread函数暂停一个线程的执行,然后呼叫GetThreadContext函数取得CONTEXT结构中相关内容。

 

下面代码查询一个线程的控制寄存器组信息:

CONTEXT Context;

SuspendThread(hThread);   

Context.ContextFlags = CONTEXT_CONTROL;

GetThreadContext(hThread, &Context);    

Context.Eip = 0x00010000;     

Context.ContextFlags = CONTEXT_CONTROL;     

SetThreadContext(hThread, &Context);    

ResumeThread(hThread);   

也就是说线程也是一个结构体,只是在高2g的内存中,我们无法访问,线程也就是eip,当20毫秒的时间片用完时,切换到其它线程,

当运行完时,在context结构中取出保存的第一个线程执行结束时的状态,继续执行。

 

线程同步的方式

关键代码段 用户方式 优点速度快 缺点 无法设置关键代码段的超时值

EnterCriticalSection LeaveCriticalSection 在使用之前需要声明一个critical_section的结构

在使用结构之前必须先进行初始化操作InitializeCriticalSection

在不使用这个结构时使用deleteCriticalSection

当一个线程试图进入另一个线程拥有的关键代码段时,调用线程就立即被置于等待状态,意味着会从用户态转换为内核态,代价是十分大的,因此使用循环锁。InitializeCriticalSectionAndSpinCount第二个参数为循环等待的次数,在单核处理器下该值无效。初始化操作失败会出现STATUS_NO_MEMOR异常

4000 通常情况下建议使用CriticalSectionAndSpinCount

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CONTEXTWindows 操作系统中一种数据结构,它用于保存 CPU 的寄存器状态和其他与进程或线程相关的信息。在 Windows 内核编程中,CONTEXT 是非常重要的数据结构,经常被用来实现线程切换和异常处理等功能。 下面是一个简单的使用 CONTEXT 的示例代码: ```c #include <Windows.h> void foo(CONTEXT& ctx) { // 在这里可以修改 ctx 中的寄存器值等信息 } int main() { CONTEXT ctx; memset(&ctx, 0, sizeof(ctx)); ctx.ContextFlags = CONTEXT_FULL; // 获取所有寄存器的值 __asm { int 3 // 调试中断,使程序停止运行,等待用户输入 mov dword ptr [ctx.Ebp], ebp mov dword ptr [ctx.Esp], esp pushad // 保存所有通用寄存器的值 } foo(ctx); __asm { popad // 恢复所有通用寄存器的值 mov ebp, dword ptr [ctx.Ebp] mov esp, dword ptr [ctx.Esp] } return 0; } ``` 上面的代码中,我们首先定义了一个名为 `foo` 的函数,它的参数是一个 CONTEXT 的引用。在函数中,我们可以修改 CONTEXT 中的寄存器值等信息,从而实现一些定制化的操作。 接下来是 `main` 函数的代码。首先我们创建了一个 CONTEXT 对象,并将它的所有成员变量都初始化为 0。然后我们设置了 `ContextFlags` 的值为 `CONTEXT_FULL`,表示需要获取所有寄存器的值。 接着,我们使用汇编语言插入了一个 `int 3` 指令,这是一个调试中断指令,它会使程序停止运行,等待用户输入。在这个过程中,我们可以使用调试器查看当前线程的寄存器状态。 在 `int 3` 指令之后,我们使用汇编语言将当前线程的 EBP 和 ESP 寄存器的值保存到 CONTEXT 中,并使用 `pushad` 指令将所有通用寄存器的值保存到堆栈中。 接着我们调用了 `foo` 函数,并将 CONTEXT 对象作为参数传递给它。在 `foo` 函数中,我们可以修改 CONTEXT 中的寄存器值等信息。这里的代码实现是不完整的,需要根据具体的需求进行修改。 最后,我们再次使用汇编语言恢复所有通用寄存器的值,并将 EBP 和 ESP 寄存器的值从 CONTEXT 中恢复回来。最后程序返回 0,结束运行。 总体来说,使用 CONTEXT 可以让我们更好地控制线程的行为,实现一些高级的操作。但是需要注意的是,如果使用不当,可能会导致系统崩溃或数据丢失等问题,因此在使用 CONTEXT 时需要格外小心。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值