首页
社区
课程
招聘
[求助]内核堆栈的个数
发表于: 2009-4-30 14:13 4638

[求助]内核堆栈的个数

2009-4-30 14:13
4638
是不是每个进程都有一个内核堆栈?他们的虚拟地址相同,但因CR3的不同而物理地址不同?如果是这样,那同一个进程中不同的线程共用一个内核堆栈,在同时进行系统调用的时候如何处理的?盼解惑。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 331
活跃值: (57)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
不使用同一个内核栈的吧,虚拟地址也都不一样……
2009-4-30 14:57
0
雪    币: 214
活跃值: (168)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
参考 http://bbs.pediy.com/showthread.php?t=60247
我用windbg看到是:不同的进程在陷入内核时SS 和 ESP 初始化是一样。但还是没有弄明白同一个进程中不同的线程,在同时进行系统调用的时候如何处理的?
2009-4-30 15:25
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
4
内核栈是每个线程都有,它位于_KTHREAD结构体中。

硬件陷入RING0时的SS与ESP是一个固定值,并不是线程的内核栈,可以认为是一个不属于任何线程的“陷阱栈”。内核栈由软件维护。
2009-4-30 17:02
0
雪    币: 331
活跃值: (57)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
[QUOTE=magicfound;614529]参考 http://bbs.pediy.com/showthread.php?t=60247
我用windbg看到是:不同的进程在陷入内核时SS 和 ESP 初始化是一样。但还是没有弄明白同一个进程中不同的线程,在同时进行系统调用的时候如何处理的?[/QUOTE]

系统调用、中断、异常进入内核时的内核栈是由TSS中的ESP0指定的,这是CPU权限切换的硬件机制决定的,ESP0就是当前线程的内核栈基址。当线程切换时TSS->ESP0也同时被改变(TSS中的其它字段基本不变,如SS)。线程被切换后的内核栈基址和SP指针都保存在_KTHREAD结构中!
2009-4-30 17:38
0
雪    币: 214
活跃值: (168)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
书呆彭:那什么时候把“陷阱栈”切换成线程的内核栈?我查看了KiFastCallEntry没有发现切换的动作。
better:在用 int 2e 进行系统调用时是要用TSS,但用 sysenter 进行系统调用时用的是msr寄存器。这个应该是全局一样的。两种调用是兼容的。
2009-4-30 18:20
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
7
“陷阱栈”是我自己编造的词,刚才看了一下WRK的文件,人家说那叫DPC堆栈,代码是这样写的(引用自WRK-v1.2\base\ntos\ke\i386\trap.asm):

...
        align 16

        PUBLIC _KiFastCallEntry
_KiFastCallEntry        proc

;
; Sanitize the segment registers
;
        mov     ecx, KGDT_R3_DATA OR RPL_MASK
        push    KGDT_R0_PCR
        pop     fs
        mov     ds, ecx
        mov     es, ecx

[COLOR="Red"];
; When we trap into the kernel via fast system call we start on the DPC stack. We need
; shift to the threads stack before enabling interrupts.
;[/COLOR]
        mov     ecx, PCR[PcTss]        ;
        mov     esp, [ecx]+TssEsp0

        push    KGDT_R3_DATA OR RPL_MASK   ; Push user SS
        push    edx                         ; Push ESP
        pushfd
...


从这段代码来看,NT内核确实是使用TSS来存放当前线程的内核栈地址的。经过查看ContextSwitch函数,证实了这一点,内核在线程切换时将新线程的内核栈地址写入TSS中的RING0栈指针相关域的。代码如下(WRK-v1.2\base\ntos\ke\i386\ctxswap.asm):

...
[COLOR="Red"];
; Adjust the initial stack address, if necessary, and store in the TSS so V86
; mode threads and 32 bit threads can share a common trapframe structure and
; the NPX save area will be accessible in the same manner on all threads.
;[/COLOR]

        mov     eax, [esi].ThInitialStack ; get initial stack address
        sub     eax, NPX_FRAME_LENGTH
.errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
        test    byte ptr [eax] - KTRAP_FRAME_LENGTH + TsEFlags + 2, EFLAGS_V86_MASK / 10000h
        jnz     short sc24              ; if nz, V86 frame, no adjustment
        sub     eax, TsV86Gs - TsHardwareSegSs ; bias for missing fields
sc24:   mov     ecx, [ebx]+PcTssCopy    ; get TSS address
        mov     [ecx]+TssEsp0, eax      ; set initial kernel stack address
...


没仔细看WRK的LICENSE,这样引用WRK中的代码片段,应该没什么吧。
2009-4-30 21:57
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
8
看了一下LICENSE,找到依据了,呵呵。
You may distribute snippets of this software in research papers, books or
other teaching materials, or publish snippets of the software on websites
or on-line community forums that are intended for teaching and research.
The total amount of source code in each of your snippets should
not exceed 50 lines. If you wish to use a larger portion
of the software, please contact [email]compsci@microsoft.com[/email].
2009-4-30 22:20
0
雪    币: 214
活跃值: (168)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
看代码不仔细呀。在ReactOS的 asmmacro.S 中,FASTCALL_PROLOG 就有切换堆栈的动作
.macro FASTCALL_PROLOG Label EndLabel

/* Set user selector */
mov ecx, KGDT_R3_DATA | RPL_MASK

/* Set FS to PCR */
push KGDT_R0_PCR
pop fs

/* Set DS/ES to User Selector */
mov ds, cx
mov es, cx

/* Set the current stack to Kernel Stack */
mov ecx, PCR[KPCR_TSS]
mov esp, [ecx+KTSS_ESP0]


谢谢书呆彭和better。“陷阱栈”名字很好啊,每个CPU一个:)
2009-4-30 23:26
0
游客
登录 | 注册 方可回帖
返回
//