在很麻煩的lab4過後,接著是也沒有多輕鬆的lab5來了,這門課真的是通往地獄的課
切記!!!! 可以參考,但是照抄真的很沒有意義,學不到東西也無法讓你帶著走,看著code回答不出來更尷尬
這次主要加入了一個很重要的概念user,以往我們的實驗都是在kernel mode的情況下去做現在需要切換mode,並且還要實作scheduling,我也是搞得懵懵懂懂,盡量用寫下來的方式,來幫助自己釐清,可能會有很多錯誤還多多包涵<! — more →
首先,我根據TODO先來到了lib/syscall.c
馬上就看到一個syscall function,提示告訴我們AX用來存syscall number,其餘都拿來放參數用,然後告訴我們voliatile這個用法是告知compiler不要去優化我們參數,這方面我也沒有很清楚,我大學不是本科系沒有修過compiler,但主要就是complier會在compile時根據他的情況可能去優化掉某些他覺得不必要或是可以精簡掉的東西
裡面有提示到如果沒有要輸入的參數可以用它提供的macro去簡化我們的工作,而他有提到要加這些syscall的interface(他少提示一個…..最後我發現要依據inc/syscall.h這裡面的function去設置)
而有參數的我們還是必須手動去設置相對應的syscall
這樣我們就設好syscall的interface了
接著我在TODO找,想要先解決task.c(這次LAB就沒有像上次一樣明確的先後順序了……至少我是這樣覺得拉,所以寫的也很痛苦)
首先我們可以看到一開始先去定義GDT的位置跟權限,也說明了這次分成user 跟kernel兩種,他幫我們完成了,再往下看會看到第一關,task_create()
其實這邊真的還好,提示把你該做的步驟都說得很清楚,首先先找到空的TASK,找不到就回傳-1
順便先去看Task的結構
接著設置此task的pgdir,這邊就要注意了,他幫你完成了,但裡面的setupkvm你必須自己來,在memory.c裡面(我搞好久才發現這邊沒寫QQ)
好那我們先看過去
根據提示,將kernel part的部分建好,可以看到下面四個步驟跟前一個lab最後在map memory的時候幾乎一模一樣,只是設置的page directory已經不再是kern_pgdir了(詳情請看上個lab)
設置完之後我們回task.c設定跟這task有關的資料結構,可以看到先確定一下是否有parent_task,並把狀態以及分配到的time quant都設好,回傳task的ID,這階段就大功告成了
這邊這個也很容易,他有提示利用lcr3來切換到kern_pgdir,接著清空user stack,page table ,page director
接下來是sys_kill,這邊主要提到說要先切換TASK的狀態,否則清掉task之後他將會永遠保持在RUNNING的狀態,你在create的時候他會被忽略掉,清完之後執行schedule,但在這邊還沒實作,後面會再提到,
接著我們看到如何去做sys_fork,這邊我覺得也是一大難題(其實換個角度說,要牽扯到memory的我覺得都很難),我們先看提示
根據第一個指示,先去create一個task,然後我們接著將parent的tf複製給child的tf(tf詳情請回去找lab3),再來你必須把stack也複製給child這邊我們用到之前的pgdir_walk幫我們找page_table在複製此addr裡的資料,記住 他只看得懂virtual address,所以必須轉成va在copy,第四步驟他已經幫我們完成了,但她需要我們去了解這個構造的原因我猜是因為linkscript將text data segment之類的已經指到那個地方去,所以USER再讓process 去做mapping時要mapping到這些地方,最後我們在將她們要回傳的pid(syscall number比較貼切)放入EAX,並回傳pid
至於task_init作業已經幫我們完成了,但他請我們自行回去看,筆者若之後有時間會再慢慢補上,記得有關init都是很重要的議題