linux切換並沒有使用x86cpu的切換方法,linux切換的實質就是cr3切換(記憶體空間切換,在switch_mm函式中)+ 暫存器切換(包括eip,esp等,均在switch_to函式中)。這裡我們講述下switch_to主流程:
1. 在switch_mm函式中將new_task->pgd設定到cr3暫存器中,實現頁表切換,由於每個程序3-4g的頁表對映機制完全一樣(從核心頁表中直接複製過來的),故這裡雖然切換了pgd,但是並無影響,只是在任務回到使用者空 間中時,才會發生變化,因為每個任務在0-3g中的頁表對映都是各自獨立的;
2. 壓入esi edi ebp到cur_task堆疊中;
3. 將esp暫存器中的值儲存到cur_task.task_struct.thread.esp中,也就是將cur_task切換時的堆疊指標儲存起來;
4. 將new_task.task_struct.thread.esp中的值設定到esp暫存器中,這裡的new_task.task_struct.thread.esp中的值就是new_task上一次被換出時的堆疊指標,現在被恢復了,2和3結合實現了從cur_task到new_task的堆疊切換;
5. 將1f位址設定到cur_task.task_struct.thread.eip中,當下次cur_task恢復執行時,將會從1f處開始執行,下面闡述了這種原理;
6. 將new_task.task_struct.thread.eip壓入到new_task的堆疊中,這裡new_task.task_struct.thread.eip的值就是1f,因為從4中可知,new_task上一次被換出時,其也是和現在的cur_task類似,1f位址被設定到new_task.task_struct.thread.eip中;
7. 隨後cpu跳轉到__switch_to函式中開始執行,注意這裡使用的是jmp,不是call,call會pusheip,而jmp不會,由於__switch_to是函式,當cpu執行完該函式後,最後一條指令必然為iret,該指令會popeip,從5中可以知道,此時new_task堆疊中的映象為[......., esi,edi,ebp,eip(&1f)],故popeip將值eip(&1f)設定到eip暫存器中,這樣當iret執行完畢後,cpu將從eip處繼續執行,也就是從1f處繼續執行;
8. 此時已經在new_task的執行環境中了,pop ebp, pop edi, popesi,回到schedule函式中,當返回使用者空間中時,由於new_task使用者空間的eip,ss,esp等均被從new_task的堆疊中彈出到對應暫存器中,從而new_task得以順利執行;
元件主流程
元件例項化期間 1.生成子元件 包括不變的子元件和變化的子元件。後者的例項可以在其它時機動態生成 2.設定預設屬性 3.新增系統級事件 4.新增自定義事件 5.為元件本身以及固定子元件附著渲染器 由元件外部呼叫 enterframe週期 6.渲染 由元件外部的渲染管理器呼叫 6.1.將子元件 不變的...
libeio原始碼分析 主流程
相信上面這段話已經將libeio的feature講的足夠清楚 提供全套非同步檔案操作的介面,讓使用者能寫出完全非阻塞的程式。阻塞意味著低效,但非阻塞一定要有很好的通知機制才能做到高效。其實linux下的aio 非同步io 並不是沒有解決方案 在使用者態,多執行緒同步來模擬的非同步io,如glibc ...
OpenSBI 主流程分析與總結
risc v指令集的sbi標準規定了類unix平台下,作業系統執行環境的規範。這個規範擁有多種實現,opensbi是它的一種實現.risc v架構中,存在著定義於作業系統之下的執行環境。這個執行環境不僅將引導啟動risc v下的作業系統,還將常駐後台,為作業系統提供一系列二進位制介面,以便其獲取和操...