<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 十一、 來源:[JOS學習筆記(十一)](http://blog.csdn.net/roger__wong/article/details/9632311) 不知不覺已經寫了11篇日志了,本篇博客將完成LAB 4的PART A的剩余部分,包括內核鎖、進程(環境)的簡單調度算法,以及fork系統調用。 ## 一、內核鎖 ### 1、鎖實現 考慮到當多個CPU同時陷入內核的場景,若對于關鍵數據結構不加鎖必然就會導致重入錯誤(如cprintf不加鎖會在屏幕上輸出奇怪的結果),因此使用鎖來保證內核函數內部的邏輯正確性是很有必要的。 內核鎖相關代碼都在spinlock.c和spinlock.h中,關鍵代碼如下: ![](https://box.kancloud.cn/2015-12-24_567b6e7bc8104.jpg) 以及x86.h里面的xchg函數: ![](https://box.kancloud.cn/2015-12-24_567b6e7bdc2f3.jpg) 可以看到,xchg函數首先使用lock指令使xchgl變為原子操作,然后嘗試將xchgl兩個操作數互換,并把原先第一個操作數的結果放入result中返回。 若此時鎖是空閑的,則xchg返回0,spin_lock函數執行完成,否則繼續執行pause指令,然后接著執行xchg函數直到其返回值為1. 關于lock引用一段匯編手冊的資料: 總線加鎖前綴“lock”,它是為了在多處理器環境中,保證在當前指令執行期間禁止一切中斷。這個前綴僅僅對ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG,DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD,XCHG指令有效,如果將Lock前綴用在其它指令之前,將會引起異常。 關于pause: 提升spin-wait-loop的性能,當執行spin-wait循環的時候,笨死和小強處理器會因為在退出循環的時候檢測到memory order violation而導致嚴重的性能損失,pause指令就相當于提示處理器哥目前處于spin-wait中。在絕大多數情況下,處理器根據這個提示來避免violation,藉此大幅提高性能,由于這個原因,我們建議在spin-wait中加上一個pause指令。(出自于intel 匯編手冊) ### 2、實驗相關: 實驗要求在以下4個地方加鎖: (1)i386_init中,啟動多個ap之前。 (2)mp_main中,開始把任務調度到cpu上之前。 (3)trap中,若從用戶態陷入內核則加鎖。 (4)env_run中,從內核態返回用戶態需要釋放鎖。 加鎖后,將原有的并行執行過程在關鍵位置變為串行執行過程,整個啟動過程大概如下: i386_init-->BSP獲得鎖-->boot_ap-->(BSP建立為每個cpu建立idle任務、建立用戶任務,mp_main)--->BSP的sched_yield-->其中的env_run釋放鎖-->AP1獲得鎖-->執行sched_yield-->釋放鎖-->AP2獲得鎖-->執行sched_yield-->釋放鎖..... 其中括號表示并行執行 具體代碼如下: (1)i386_init ![](https://box.kancloud.cn/2015-12-24_567b6e7be95be.jpg) (2)mp_main ![](https://box.kancloud.cn/2015-12-24_567b6e7c0264e.jpg) (3)trap ![](https://box.kancloud.cn/2015-12-24_567b6e7c15658.jpg) (4)env_run ![](https://box.kancloud.cn/2015-12-24_567b6e7c26344.jpg) ## 二、任務調度 ### 1、原理 在JOS中,任務調度在內核中是函數sched_yield,同時在用戶態有相應的系統調用sys_yield也可以調用內核中的這個函數。 i386_init啟動時,在boot_ap函數調用后,為每個CPU創建一個idle任務,相應代碼在user/idle.c,通過代碼可以看到,這些任務使用一個死循環,不斷調用sys_yield嘗試切換任務。 所以在這種機制下我們需要實現sched_yield函數,具有以下幾個要求: (1)找到狀態為runnable的任務,并切換執行 (2)如果找到一個running狀態的任務,且此任務執行的CPU為當前CPU,也可將此任務切換執行 (3)若沒有runnable任務,則執行idle任務。 (4)從當前CPU執行的任務處開始遍歷鏈表(為了保證公平性) ### 2、代碼 sched_yield的任務調度代碼如下: ![](https://box.kancloud.cn/2015-12-24_567b6e7c413d3.jpg) 首先找到CPU當前任務的下標,然后從下標的下一個開始遍歷數組。博主這段代碼寫的比較笨,主要是為了方便調試所用。 同時還要增加系統調用的部分代碼,把進入內核態后的系統調用號和具體的系統調用對應起來,較為容易故不再詳細論述。 ## 三、fork ### 1、原理 fork作為一個系統調用,其功能是根據父進程創建出一個一模一樣的子進程,若返回的是0則說明是子進程,否則是父進程,同時返回值為子進程的系統調用號。 JOS實現fork過程采用的是用戶態“類庫”的形式封裝了一系列系統調用,包括創建新進程、設置新進程狀態、虛擬地址映射等等,這部分已經在user/dumbfork.c中封裝好了,實驗所要求的是實現相關的系統調用,包括: + sys_exofork:若為父進程返回子進程號,子進程則返回0。 + sys_env_set_status:設置子進程格式為runnable或者not_runnable + sys_page_alloc:分配一個物理頁并對應到某個虛擬地址 + sys_page_map:拷貝父進程的某個PTE,以此來建立子進程的虛擬內存映射 + sys_page_unmap:解除某個虛擬地址的映射(在PART B中使用) ### 2、代碼 sys_exofork: ![](https://box.kancloud.cn/2015-12-24_567b6e7c556f7.jpg) 可以看出,該函數首先復制各寄存器的狀態(env_tf),然后系統調用本身返回子進程的id,因為調用此系統調用的進程為父進程。同時將子進程的eax寄存器設置為0,因為系統調用的結果存放在eax寄存器中,這樣子進程返回后得到的系統調用返回結果就為0。 sys_env_set_status ![](https://box.kancloud.cn/2015-12-24_567b6e7c64407.jpg) 首先判斷狀態會否合法,然后根據進程ID進行查找,最后設置狀態并返回。 sys_page_alloc: ![](https://box.kancloud.cn/2015-12-24_567b6e7c725c3.jpg) 按實驗要求判斷各種條件。 sys_page_map: ![](https://box.kancloud.cn/2015-12-24_567b6e7c85897.jpg) 主要是一些判斷+LAB 2中的函數的封裝,沒什么可說的。 sys_page_unmap: ![](https://box.kancloud.cn/2015-12-24_567b6e7ca08c5.jpg) 到此PART A基本結束了,運行結果如下: ![](https://box.kancloud.cn/2015-12-24_567b6e7cb427d.jpg) PS:寫起來怎么感覺這個實驗好簡單啊,做起來怎么感覺難到爆啊。。。。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看