阅读:1490回复:9
很糊涂的问题,大家多指点。
几个问题:
1.系统启动进入内核之后ring0,最后必然要回到用户态,这其中的切换需要什么代价? 是如何切换的?比如设置哪些状态,保护什么东东标志? 比如ring3可以通过 int 2e进入ring0,那么ring0怎么回到ring3. 2.关于system service. 我想win 32 api最终会调用native api。但是ntdll.dll和ntoskrnl.exe都会导出Ntxxxx,那么这个native api到底是哪个导出的? ntdll.dll中的Ntxx通过int 2e进入内核, ntoskrnl.exe的Zwx也通过int 2e进入内核,为什么还要设计两个东东都通过int 2e进入,一个不就完了吗? ntdll.dll运行ring3态,可以被用户程序调用,ntoskrnl.exe运行ring0态,是否只能被kernel mode程序调用? Zwxx通过int 2e重入ring0时,由于pre mode=ring0,所以没有安全检查?? --------------- 后两个问题我同学问: 3.windows 2000为何要把gui,user也搞进kernel,有何大用? 4.为何system service用int 2e进入,而不用callgate?? ------------------- 有点罗嗦,但是确实很糊涂,希望得到大家的指点。 |
|
沙发#
发布于:2002-11-28 11:35
几个问题: |
|
板凳#
发布于:2002-11-28 11:37
补充一下,从ring0返回ring3的时候还要检查是否需要进程切换,有没有apc在排队。。。。
|
|
地板#
发布于:2002-11-28 12:33
多谢ysy
呵呵,大家继续讨论。 |
|
地下室#
发布于:2002-11-28 12:36
下面是pjf的解释。
------------------------------ 1.系统启动进入内核之后ring0,最后必然要回到用户态,这其中的切换需要什么代价? 是如何切换的?比如设置哪些状态,保护什么东东标志? //范围so大,岂是几句能说清楚的 比如ring3可以通过 int 2e进入ring0,那么ring0怎么回到ring3. //ft iretd ,sysexit,...... 2.关于system service. 我想win 32 api最终会调用native api。但是ntdll.dll和ntoskrnl.exe都会导出Ntxxxx,那么这个native api到底是哪个导出的? //最后进入的是同一个由SSDT纪录的函数里,前者所做的预处理多一 //点而已。另外ntoskrnl导出的NT***与ntdll的不同,ntoskrnl的 //Zw***才用了int2e等。 ntdll.dll中的Ntxx通过int 2e进入内核, ntoskrnl.exe的Zwx也通过int 2e进入内核,为什么还要设计两个东东都通过int 2e进入,一个不就完了吗? //显然,自己想想看 ntdll.dll运行ring3态,可以被用户程序调用,ntoskrnl.exe运行ring0态,是否只能被kernel mode程序调用? //of course Zwxx通过int 2e重入ring0时,由于pre mode=ring0,所以没有安全检查?? //right --------------- 后两个问题我同学问: 3.windows 2000为何要把gui,user也搞进kernel,有何大用? //说法不准确,效率 4.为何system service用int 2e进入,而不用callgate?? //1、看看unix的核,想想它们的关系;2、看看由那些机器有callgate;3、XP在大多数机器上都不用int2e。 |
|
5楼#
发布于:2002-11-28 16:56
pjf说的比较粗,但是我还是支持他的,的确不是几句话就能说明白的。你问的这些问题看似很简单但是需要对cpu的结构有个很清楚的了解,我也觉得真正弄明白的话需要看很多书,还需要时间,除非你是天才。
|
|
6楼#
发布于:2002-11-28 18:38
呵呵,真正弄清楚决非一件容易的事情。
也许很多人知道结论,但是不一定就清楚他真正的内部实现机制,也是个似懂非懂。 要想搞定,要自己专心研究,看书,查资料,讨论也是必不可少,也许一个提示就茅塞顿开。 continue. |
|
7楼#
发布于:2002-11-28 20:12
其它诸点都不怎么成问题,稍微看一下NT代码即可窥出大概;至于第一点本身描述不甚清楚,“系统启动进入内核之后ring0,最后必然要回到用户态,这其中的切换需要什么代价?”似乎想让人从启动后如何创建system进程说起、直至控制交付某个应用的ring3部分呢,够写半本书。如果很想了解,又不想读NT的汇编码的话,建议去仔细读linux中断与系统调用、进程控制、内存管理(多可略,不过进程空间的一点东西在switch_mm中涉及)部分代码(实在想缩小范围,但实在相关),反过来读NT,你会发现大量相似之处,很容易理解。假若你仅仅是指从ring0退回到ring3那一点点过程的话,那跟其它问题也没什么区别。退回的过程有几种情形,系统调用返回是一种,自己看看很少几行的代码吧,下面是贴过的系统服务处理返回代码,很少的代码只配了简单注释(来自XP):
0008:804D4DCD PUSH 00 0008:804D4DCF PUSH EBP 0008:804D4DD0 PUSH EBX 0008:804D4DD1 PUSH ESI 0008:804D4DD2 PUSH EDI 0008:804D4DD3 PUSH FS 0008:804D4DD5 MOV EBX,00000030 0008:804D4DDA MOV FS,BX 0008:804D4DDD PUSH DWORD PTR [FFDFF000] 0008:804D4DE3 MOV DWORD PTR [FFDFF000],FFFFFFFF 0008:804D4DED MOV ESI,[FFDFF124] //ETHREAD=>ESI 0008:804D4DF3 PUSH DWORD PTR [ESI+00000140] 0008:804D4DF9 SUB ESP,48 0008:804D4DFC MOV EBX,[ESP+6C] //byte ptr[ESP+6C]=08 0008:804D4E00 AND EBX,01 0008:804D4E03 MOV [ESI+00000140],BL //BL(0)=>ETHREAD.PreviousMode 0008:804D4E09 MOV EBP,ESP 0008:804D4E0B MOV EBX,[ESI+00000134] //old ETHREAD.TrapFrame=>EBX 0008:804D4E11 MOV [EBP+3C],EBX 0008:804D4E14 MOV [ESI+00000134],EBP 0008:804D4E1A CLD 0008:804D4E1B TEST BYTE PTR [ESI+2C],FF //debug flag is active? 0008:804D4E1F JNZ 804D4CEC 0008:804D4E25 STI 0008:804D4E26 MOV EDI,EAX 0008:804D4E28 SHR EDI,08 0008:804D4E2B AND EDI,30 0008:804D4E2E MOV ECX,EDI 0008:804D4E30 ADD EDI,[ESI+000000E0] //get ServiceTable 0008:804D4E36 MOV EBX,EAX 0008:804D4E38 AND EAX,00000FFF 0008:804D4E3D CMP EAX,[EDI+08] //correct ServiceId? 0008:804D4E40 JAE 804D4CA2 0008:804D4E46 CMP ECX,10 //extended Service? 0008:804D4E49 JNZ 804D4E65 0008:804D4E4B MOV ECX,[FFDFF018] 0008:804D4E51 XOR EBX,EBX 0008:804D4E53 OR EBX,[ECX+00000F70] 0008:804D4E59 JZ 804D4E65 0008:804D4E5B PUSH EDX 0008:804D4E5C PUSH EAX 0008:804D4E5D CALL [80544C44] 0008:804D4E63 POP EAX 0008:804D4E64 POP EDX 0008:804D4E65 INC DWORD PTR [FFDFF638] 0008:804D4E6B MOV ESI,EDX 0008:804D4E6D MOV EBX,[EDI+0C] 0008:804D4E70 XOR ECX,ECX 0008:804D4E72 MOV CL,[EBX+EAX] //get bytes of parameters 0008:804D4E75 MOV EDI,[EDI] 0008:804D4E77 MOV EBX,[EAX*4+EDI] //get the service function address 0008:804D4E7A SUB ESP,ECX 0008:804D4E7C SHR ECX,02 0008:804D4E7F MOV EDI,ESP 0008:804D4E81 CMP ESI,[ntoskrnl!MmUserProbeAddress] 0008:804D4E87 JAE 804D5033 //do something if ... from ring0 0008:804D4E8D REPZ MOVSD //copy parameters 0008:804D4E8F CALL EBX //call service function 0008:804D4E91 MOV ESP,EBP 0008:804D4E93 MOV ECX,[FFDFF124] 0008:804D4E99 MOV EDX,[EBP+3C] 0008:804D4E9C MOV [ECX+00000134],EDX 0008:804D4EA2 CLI 0008:804D4EA3 TEST DWORD PTR [EBP+70],00020000 //v86 mode? 0008:804D4EAA JNZ 804D4EB2 0008:804D4EAC TEST BYTE PTR [EBP+6C],01 //ring0 or ring3? 0008:804D4EB0 JZ 804D4F08 0008:804D4EB2 MOV EBX,[FFDFF124] 0008:804D4EB8 MOV BYTE PTR [EBX+2E],00 0008:804D4EBC CMP BYTE PTR [EBX+4A],00 //for APC 0008:804D4EC0 JZ 804D4F08 0008:804D4EC2 MOV EBX,EBP 0008:804D4EC4 MOV [EBX+44],EAX 0008:804D4EC7 MOV DWORD PTR [EBX+50],0000003B 0008:804D4ECE MOV DWORD PTR [EBX+38],00000023 0008:804D4ED5 MOV DWORD PTR [EBX+34],00000023 0008:804D4EDC MOV DWORD PTR [EBX+30],00000000 0008:804D4EE3 MOV ECX,00000001 0008:804D4EE8 CALL [HAL!KfRaiseIrql] 0008:804D4EEE PUSH EAX 0008:804D4EEF STI 0008:804D4EF0 PUSH EBX 0008:804D4EF1 PUSH 00 0008:804D4EF3 PUSH 01 0008:804D4EF5 CALL ntoskrnl!KiDeliverApc 0008:804D4EFA POP ECX 0008:804D4EFB CALL [HAL!KfLowerIrql] 0008:804D4F01 MOV EAX,[EBX+44] 0008:804D4F04 CLI 0008:804D4F05 JMP 804D4EB2 0008:804D4F07 NOP //go on 0008:804D4F08 MOV EDX,[ESP+4C] 0008:804D4F0C MOV EBX,FS:[00000050] 0008:804D4F13 MOV FS:[00000000],EDX 0008:804D4F1A MOV ECX,[ESP+48] 0008:804D4F1E MOV ESI,FS:[00000124] 0008:804D4F25 MOV [ESI+00000140],CL 0008:804D4F2B TEST EBX,0000000F 0008:804D4F31 JNZ 804D4FA8 0008:804D4F33 TEST DWORD PTR [ESP+70],00020000 0008:804D4F3B JNZ 804D57EA 0008:804D4F41 TEST WORD PTR [ESP+6C],FFF8 0008:804D4F48 JZ 804D5001 0008:804D4F4E CMP WORD PTR [ESP+6C],1B 0008:804D4F54 BT DWORD PTR [ESP+6C],00 0008:804D4F5B CMC 0008:804D4F5C JA 804D4FEF ;if(DT!=1B&ÐREAD.PreviousMode==UserMode) error; 0008:804D4F62 CMP WORD PTR [EBP+6C],08 0008:804D4F67 JZ 804D4F6E 0008:804D4F69 LEA ESP,[EBP+50] 0008:804D4F6C POP FS 0008:804D4F6E LEA ESP,[EBP+54] 0008:804D4F71 POP EDI 0008:804D4F72 POP ESI 0008:804D4F73 POP EBX 0008:804D4F74 POP EBP 0008:804D4F75 CMP WORD PTR [ESP+08],0080 0008:804D4F7C JA 804D5806 0008:804D4F82 ADD ESP,04 0008:804D4F85 TEST DWORD PTR [ESP+04],00000001 0008:804D4F8D JNZ 804D4F95 0008:804D4F8F POP EDX 0008:804D4F90 POP ECX 0008:804D4F91 POPFD 0008:804D4F92 JMP EDX //return to ring0 (edx=>eip) 0008:804D4F94 IRETD 0008:804D4F95 POP EDX 0008:804D4F96 ADD ESP,08 0008:804D4F99 POP ECX 0008:804D4F9A STI 0008:804D4F9B SYSEXIT //return to ring3 (edx=>eip,ecx=>esp) 0008:804D4F9D POP ECX 0008:804D4F9E ADD ESP,08 0008:804D4FA1 POP ESP 0008:804D4FA2 SYSRET //for AMD cpu 0008:804D4FA4 IRETD 0008:804D4FA5 LEA ECX,[ECX+00] 0008:804D4FA8 TEST DWORD PTR [EBP+70],00020000 0008:804D4FAF JNZ 804D4FBE 0008:804D4FB1 TEST DWORD PTR [EBP+6C],00000001 0008:804D4FB8 JZ 804D4F33 0008:804D4FBE MOV EBX,00000000 0008:804D4FC3 MOV ESI,[EBP+18] 0008:804D4FC6 MOV EDI,[EBP+1C] 0008:804D4FC9 MOV DR7,EBX 0008:804D4FCC MOV DR0,ESI |
|
8楼#
发布于:2002-11-29 13:07
多谢了。
|
|
9楼#
发布于:2002-12-01 14:44
看了大补!
|
|