在做二级下拉菜单动的时候,一般需要动态的给第二个下拉菜单赋值(有时候第一个下拉菜单也是动态加载数据),一般的下拉框的样式比较丑,当使用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 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现
?
?