- 论坛徽章:
- 1
|
本帖最后由 openspace 于 2010-02-21 17:28 编辑
回复 7# 1226ehziy
刚才看esp看的稀里糊涂的
重新整理了一下
long esp;
__asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (THREAD_SIZE - 1));
// 输出变量esp与0号寄存器关联,而后面会将0号寄存器的值设置为THREAD_SIZE - 1
// 假设THREAD_SIZE大小为4K,即1<<12,那么THREAD_SIZE - 1的值为 1111 1111 1111
// 而%esp是内核堆栈的栈顶指针
// x86中,栈的增长方向为高地址向低地址增长
// 这样andl %%esp,%0实际上取的是%esp的相对值存放到变量esp中
// 注意这里的“相对“;
// 要知道%esp的绝对值是一个线性地址,其值可能非常大,进程的内核栈的起始地址也可能是一个非常大的值
// 想知道内核栈中实际使用的栈空间该如何计算呢?
// 这里利用了栈的起始地址是THREAD_SIZE的整数倍这个特点,栈顶又是在一个进程的内核栈之中
// 想知道内核栈中实际使用的栈空间,需要获取相对于THREAD_SIZE下的一个值,或者可以看作是取模操作,
// 这里andl与操作就是要完成这个计算
if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
// 从这里的检测来看,内核栈中应该是低地址部分存放thread_info结构
// 但是为了保险期间,会在thread_info结构和栈之间放入STACK_WARN大小的隔离层
// 而如果栈顶从高地址往下增长到该隔离层,就会给出栈溢出的信息
printk("co_switch_wrapper: stack overflow: %ld\n", esp - sizeof(struct thread_info));
co_terminate(CO_TERMINATE_STACK_OVERFLOW);
} |
|