他猛地看向钱学敏,眼神中充满了惊疑。
“你的意思是……”
“你想想,”钱学敏的思路像一道闪电,划破了混乱的局面,“我们创建了任务A和任务B。但是,我们好像……忘了给它们各自指定一块独立的内存,作为它们自己的堆栈空间!”
黄建功的脸色,瞬间变得惨白。
他明白了。
他彻底明白了!
这是一个如此巨大,却又如此隐蔽的,思想上的钢印!
在他们的潜意识里,在过去所有的编程经验里,一个程序,永远只有一个堆栈!
整个系统,从头到尾,都共享着那块由系统在启动时分配好的,唯一的堆栈内存。
所以,当他们设计“天枢”内核时,尽管他们天才般地想到了要为每个任务保存寄存器、程序计数器等“上下文”。
但他们,却完完全全,彻彻底底地,忽略了最重要的一样东西!
堆栈!
每个任务,都应该有自己独立的,互不干扰的堆栈空间!
而他们做了什么?
他们让任务A和任务B,共用了同一个堆栈!
黄建功的脑海中,瞬间浮现出灾难发生的全过程。
1. 系统启动,分配了一个全局堆栈。
2. 任务A开始运行,它调用了一些函数,在堆栈里压入了一些自己的数据,比如局部变量、返回地址。
3. 任务A调用`system_yield()`,触发任务切换。
4. “天枢”内核执行,将任务A的寄存器(包括那个指向公共堆栈的SP指针)保存到任务A的PCB里。
5. 内核切换到任务B。
6. 任务B开始运行。它也调用了函数,它也需要在堆栈里压入数据。但是!它使用的,是和任务A完全相同的那个堆栈!
7. 于是,任务B的数据,就把任务A之前存放在堆栈里的数据,给覆盖了!冲掉了!
灾难,在这一刻就已经注定。
8. 任务B运行了一会儿,也调用了`system_yield()`。
9. 内核再次切换,轮到任务A运行。
10. 内核从任务A的PCB里,恢复了任务A所有的寄存器,包括那个SP指针。
11. 任务A从上次暂停的地方继续执行。它准备从堆栈里弹出自己之前存入的返回地址,准备返回上一个函数。