当前位置:职场发展 > VS2010轮播滚动源码_Windows线程(模拟线程切换、主动切换、时钟中断切换、时间片管理、TSS...

VS2010轮播滚动源码_Windows线程(模拟线程切换、主动切换、时钟中断切换、时间片管理、TSS...

  • 发布:2023-09-21 16:22

在做二级下拉菜单动的时候,一般需要动态的给第二个下拉菜单赋值(有时候第一个下拉菜单也是动态加载数据),一般的下拉框的样式比较丑,当使用selectpicker进行下拉菜单美化时,有可能导致下拉菜单加载不进来,这里对这个问题做一个完美解决。 1.一般的下拉框二级联动实现

2.为了美化下拉框,引入 bootstrap-combined.min.css bootstrap-select.css bootstrap-select.js 以及bootstrap.min.js等几个常用的bootstarp文件 然后只要给select 加上 class=“selectpicker”; 这时再次用ajax 请求数据的时候,发现下拉列表加载不了option了,但是我们可以通过查看元素发现option确实在select标签下面,至此已经发现问题所在了,只能想办法解决了。在网上找了一圈没找到解决方案,最后在ajax成功请求数据之后,加上如下代码就完美解决啦。

www.sychzs.cnpicker('refresh');

www.sychzs.cnpicker('refresh');

ThreadSwitch源码分析

线程结构体(ThreadSwitch源码仿照EHREAD)

typedef struct {

char *name;//线程名 相当于线程TID

int Flags;//线程状态

int SleepMillisecondDot;//休眠时间

void *InitialStack;//线程堆栈起始位置

void *StackLimit;//线程堆栈界限

void *KernelStack;//线程堆栈当前位置,也就是ESP

void *lpParameter;//线程函数的参数

void (*func)(void *lpParameter);//线程函数

}GMThread_t;

调度链表(ThreadSwitch)

//线程结构体数组 extern GMThread_t GMThreadList[MAXGMTHREAD];

所谓创建线程,就是创建一个结构体,并且挂到这个数组中,此时的线程状态为:创建

这个ThreadSwitch进行简化,在Windows下正在运行的线程在KPCR里,等待的线程

在等待链表表里,就绪线程在就绪链表里。

ThreadSwitch分析发现只有一个线程结构体数组,其中的Flags线程状态便是代表了

线程不同的状态。

在ThreadSwitch线程结构体中其余线程是从下标1开始的,而下标0是当前线程,

main线程运行在0下标。

经典线程堆栈切换

__asm{

push ebp

push ebp,esp

push edi

push esi

push ebx

push ecx

push edx

push eax

mov esi,当前线程结构体指针

mov edi,你要切换线程的结构体指针

mov [esi+KernelStack当前线程结构体中esp的位置属性进行保存],esp

//经典堆栈切换,另一个线程复活

mov esp,[edi+KernelStack将要切换的线程esp拿出来赋值给esp]

pop eax

pop edx

pop ecx

pop ebx

pop esi

pop edi

pop ebp

ret

}

模型线程切换总结

1.线程切换不是被动切换的,而是主动让出CPU。

2.线程切换并没有使用TSS来保存寄存器,而是使用堆栈。

3.线程的切换本质上就是堆栈的切换。

4.可是使用任意的堆模拟栈的机制,将寄存器保存后进行堆栈的切换即可实现线程的变换。

主动切换

线程切换

在ThreadSwitch项目中有一个重要的函数,

SwitchContext调用这个函数后会触发经典的堆栈切换,

导致线程的切换,在Windows中也有类似的函数:

KiSwapContext。

主动线程切换总结

1.Windows中绝大部分API都调用了SwapContext函数,

也就是说,当线程只要调用了API,也就是导致了线程切换。

2.线程切换时会比较是否属于同一个进程,如果不是,切换CR3

,CR3换了,进程也就切换了。

3.调用过程:KiSwapContext的父函数,KiSwapThread

时钟中断切换

SwapContext

绝大多数的内核函数都会使用SwapContext来实现线程的切换。

如何中断一个正在执行的程序

1.异常 比如缺页,或者INT N指令。

2.中断 比如时钟中断。

系统时钟

(IDT表)中断号 |IRQ |说明

0x30 IRQ0 时钟中断

Windows系列操作系统:10-20毫秒

如要获取当前时钟间隔值,可以使用WIN32 API:

GetSystemTimeAdjustment

时钟中断要执行流程

时钟中断执行流程:

KiStartUnexpectedRange

KiEndUnexpectedRange

KiUnexpectedInterruptTail

HalBeginSystemInterrupt

HalEndSystemInterrupt

KiDispatchInterrupt

SwapContext

时钟中断切换总结

线程切换的几种情况:

1.主动调用API函数

2.时钟中断

3.异常处理

如果一个线程不调用API,在代码中屏蔽中断(CLI指令),并且

不会出现异常,那么当前线程将永久占有CPU,单核占有率100%,

2核就是50%。

时间片管理

时钟与线程切换

时钟中断会导致线程切换,但并不是说

只要有时钟中断就一定会切换线程,时钟中断时,两种情况会导致线程切换。

1.当前的线程CPU时间片到期

2.有备用线程(KPCR.PrcbData.NextThread)

有备用线程就算当前线程的时间片没有到期仍然会切换线程,

备用线程优先级高于时间片。

CPU时间片

1.当一个新的线程开始执行时,初始化程序会在_KTHREAD.Quantum

赋初始值,该值的大小由_KPROCESS.ThreadQuantum决定。

2.每次时钟中断会调用KeUpdateRunTime函数,该函数每次将当前线程

Quantum减少3个单位,如果减到0,则将KPCR,PrcbData.QuantumEnd的值设置为0

3.KiDispatchInterrupt判断时间片到期:

调用KiQuantumEnd(重新设置时间片,找到要运行的线程)。

线程切换的3种情况

1.当前线程主动调用API:

API函数->KiSwapThread->KiSwapContext->SwapContext

2.当前线程时间片到期:

KiDispatchInterrupt->KiQuantumEnd->SwapContext

3备用线程

KiDispatchInterrupt->SwapContext

线程与TSS

SwapContext

SwapContext这个函数是Windows线程切换的核心,

无论是主动切换还是系统时钟导致的线程切换,最终都会调用这个函数。

该函数除了切换堆栈以外,还做了很多其他的事情。

调用API进0环

普通调用:通过TSS.ESP0得到0环堆栈。

快速调用:从MSR得到一个临时0环栈,代码执行后仍然通过

TSS.ESP0得到当前线程0环堆栈。

TSS

Intel设计TSSS的目的是为了任务切换(线程切换),但Windows和

Linux并没有使用。而是采用堆栈保存线程的各种寄存器。

线程与FS

线程切换与FS寄存器之间的关系

FS:[0]寄存器在3环时指向TEB,进入0环后FS:[0]指向KPCR,

系统中同时存在多个线程,这就意味着FS:[0]在3环时指向的TEB要有多个(每个线程一份)。

但是在实现中3环查看不同线程的FS寄存器时,FS的段选择子都是相同的,具体是操作系统

将新的TEB地址从KPCR里读出来之后,写到当前GDT表段描述符的Base基址里面,因此

在3环中FS的段选择子是不同修改的,改变的FS对应的基址,变成的了新的线程的TEB的基址。

线程优先级

三种情况导致线程切换

(1)当前线程主动调用API

API函数:KiSwapThread、KiSwapContext、SwapContext

(2)当前线程时间片到期

KiDispatchInterrupt: KiQuantumEnd、SwapContext

(3)有备用线程(KPCR.PrcbData.NextTread)

KiDispatchInterrupt SwapContext

线程调用链表

在xp中调度链表有32个,优先级最高的位于0号链表其次位于1号链表,

以此类推,类似于KiFindReadyThread查找线程级别,是一种比较暴力

的线程优先级查找方式,比如先从31查看是否有线程,在查看30..29..28是否有线程,

如果31有线程则不会再去查找30是否有线程,需要注意的是只有在本次查找中,当

高级别的线程在执行的时候,使用了API或者时间片到期了,低级别的线程仍然有机会运行。

Windows调度链表算法

在xp中调度链表有32个,每次都重都开始查找效率较低,Windows使用DWORD变量

来进行记录,当向调度链表(32个)中挂入或者摘除某个线程时,会判断当前级别的链表

是否为空,为空将DWORD变量对应位置0,否则置1(具有等待调度线程),DWORD正好是32位。

多CPU会随机寻找KiDispatcherReadyListHead指向的数组中的线程,线程可以绑定某个

CPU(使用API:setThreadAffinityMask)。

如果没有就绪线程如何处理

在KPCR中有一个子结构体叫做PrcbData有3个重要成员

+0x004 CurrentThread:Ptr32_KTHREAD 当前线程

+0x008 NextThread:Ptr32_KTHREAD 备用线程

+0x00C ldleThread:Ptr32_KTHREAD 空闲线程

空闲线程:当CPU查找调度链表如果没有其他需要调度的线程,

这就会调度空闲线程,每个KPCR都会指定一个空闲线程。

??????? 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用。客户端是Window7操作系统,54寸大屏电脑电视一体机。要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作。当然满足客户的要求也可以有其它途径。但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用。所以在项目接来以后,也就赶鸭子上架了,经过努力奋斗最终还是搞定了。当然这里得感谢MSDN和搜索引擎。

?

凹面墙或者叫远景墙:

?

?

凸面墙或者叫近景墙:

?

----------------------------------------------------------------------------------------------------------------------------------

希望对您有所启发,激起你对WPF的热爱!有兴趣的童鞋,可以留言!邮箱:support@www.sychzs.cn??

2014年7月5日

Kevin.Chen???? 蘇州.娄城

O(∩_∩)O~

?

-----------------------------------------------------------------------------------------------------------------------------------

WPF技术触屏上的应用系列(六): 视觉冲击、超炫系统主界面、系统入口效果实现

WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果

WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、轮播、图片倒影立体滚动)效果实现

WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放、播放、暂停、可拖动播放进度效果实现

WPF技术触屏上的应用系列(二): 百度地图嵌入、API调用及结合本地数据库在地图上进行自定义标点的实现

WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现

?

?

相关文章

热门推荐