該文件是進程實現以及啟動第一個進程的主要實現部分。
還是從文件開頭說起,先看代碼:
1 #include <string.h>
2 #include <asm/system.h>
3 #include <winixj/mm.h>
4 #include <winixj/int.h>
5 #include <winixj/mailbox.h>
6 #include <winixj/process.h>
7 #include <winixj/schedule.h>
8
9 //所有進程所擁有的內核態堆棧都放到一起
10 //進程的內核態堆棧的作用主要是用來保存
11 //進程被打斷時的現場信息
12 KSTACK kstack_list[NR_PROCS];
13
14 /*********************************************
15 * 這只是權宜之計,因為我們還沒有實現內存管理
16 * 所以暫時使每個進程都有一個獨立的用戶態堆棧
17 *********************************************/
18 //所有進程所擁有的用戶太堆棧也都放到一起
19 USTACK ustack_list[NR_PROCS];
20
21 //進程鏈表,保存所有的進程控制塊信息
22 //這是全局變量
23 PROCESS proc_list[NR_PROCS];
24
25 PROCESS *current; //指向當前正在運行的進程
26
先看幾個變量的含義:
首先是kstack_list和ustack_list,在
該博文中已經說到了,每個進程都有自己單獨的用戶態棧和核心態棧,在這里的WinixJ的實現目前比較幼稚,就是申請一個數組,將所有的用戶態棧放到一起成為數組,將所有的核心態放到一起組成數組,這樣做是有嚴重問題的:每個進程的數據段和堆棧段是分開放置的,數據段在進程地址空間中,而堆棧段則在內核空間中,這樣極不利于進程之間的隔離與保護,但是誰讓我們是miniOS呢,這樣實現至少現在也能用,等實現了分頁機制以及內存管理后再改進也不遲。
然后是proc_list數組,該數組是整個進程的核心,它其中的每一項都是一個進程的心臟---進程控制塊。先看進程控制塊的定義,看它有哪些字段組成:
1 //目前的進程控制塊結構不妨盡量簡單
2 //因為我們要實現的是簡陋的進程,請忍受這一點
3 typedef struct task_struct
4 {
5 uint32 state; //進程狀態
6 uint32 priority; //進程優先級
7 uint32 time_slices; //進程的剩余時間片
8 uint32 pid; //進程的pid
9 uint32 ppid; //父進程的pid
10 #define PROC_NAME_LEN 32 //進程名的最大長度為32字節
11 char name[PROC_NAME_LEN];
12 uint32 *kstack; //指向內核態堆棧頂
13 uint32 *ustack; //指向用戶態堆棧頂
14 uint32 running_time; //進程一共運行了的時間
15 struct seg_struct ldt[3]; //進程的局部描述符表一項為空、一項為cs、一項為ds和ss
16 TSS tss;
17 } PROCESS;
18
可以看到,我們所熟知的字段都包含了,有:進程狀態、進程優先級、進程運行時間片、進程pid、父進程pid、進程名等等,還有我們剛才提到的該進程的用戶態棧和核心態棧指針,以及該進程運行了多長時間(該參數目前版本的WinixJ還沒有用到),還有ldt、tss。下面依次對其進行介紹:
1、state,有如下幾種狀態:
1 #define PROC_RUNNING 1
2 #define PROC_INTERRUPTIBLE 2
3 #define PROC_UNINTERRUPTIBLE 3
4 #define PROC_ZOMBIE 4
5 #define PROC_STOPPED 5
6
這些定義符合大部分UNIX類系統的規定。不過在WinixJ中第2、3、4種狀態目前沒有用到,進程只有正在運行、就緒兩種狀態,而RUNNING則代表了這兩種狀態,STOPPED是進程控制塊中的初始狀態,代表進程不存在(這里與UNIX類系統有些沖突,不過可以很容易修正),目前還不支持進程的死亡退出以及僵尸進程。
2、priority,進程的優先級,WinixJ目前采用的是時間片輪轉調度,因此priority和進程的初始時間片相同。
3、time_slices,進程時間片,該值越大則進程獲得運行的時間越長。
4、pid,進程pid。
5、ppid,父進程pid。
6、name[32],進程名。
7、kstack,核心態堆棧頂,前面介紹過了。
8、ustack,用戶態堆棧頂,核心態堆棧和用戶態堆棧都是1KB大小,見下面的定義:
1 //進程所擁有的內核態以及用戶態堆棧
2 //大小為1KB,短期內應該夠用
3 typedef struct kstack
4 {
5 uint8 res[1024];
6 } KSTACK, USTACK;
7
9、running_time,進程已經運行了多長時間,目前未使用該變量。
10、ldt[3],局部描述符表,定義和GDT相同,如下:
1 //定義段描述符結構,每個描述符占用8個字節
2 typedef struct seg_struct
3 {
4 uint16 seg_limit_low16;
5 uint16 seg_base_low16;
6 uint8 seg_base_mid8;
7 uint8 attr1;
8 uint8 attr2_limit_high4;
9 uint8 seg_base_high8;
10 };
11
ldt是進程間隔離的核心部件之一,每個進程都有自己的ldt,它的含義和gdt項沒有什么不同,只不過它僅包含三項,第一項和GDT的第一項一樣未空,不使用,第二項為局部CS段描述符,第三項為局部DS和SS段描述符。而這個ldt又如何使用呢?暫時不需要管,只需要知道,當發生進程切換的時候,進程的CS段和DS段基地址是從該進程的ldt中獲得的。
11、tss,這是TSS段,在進行任務切換的時候用于進程現場的保護和恢復。
再繼續往下看代碼:
1 extern void init();
2 extern void sys();
3
4 static void set_tss_seg(int n, void *addr)
5 {
6 gdt[n].seg_limit_low16 = 0x0068; //tss段長為104個字節,不能多也不能少
7 gdt[n].seg_base_low16 = (uint16)(((uint32)addr) & 0xffff); //段地址的低16位
8 gdt[n].seg_base_mid8 = (uint8)((((uint32)addr) >> 16) & 0xff); //段地址的中間8位
9 gdt[n].attr1 = 0x89; //該段在內存中存在,DPL=0,是TSS描述符
10 gdt[n].attr2_limit_high4 = 0x40; //段界限粒度是字節
11 gdt[n].seg_base_high8 = (uint8)((((uint32)addr) >> 24) & 0xff); //段地址的高8位
12 }
13
14 static void set_ldt_seg(int n, void *addr)
15 {
16 gdt[n].seg_limit_low16 = 0x0018; //所有進程的ldt均只包含三個描述符,因此ldt段長為24個字節
17 gdt[n].seg_base_low16 = (uint16)(((uint32)addr) & 0xffff); //段地址的低16位
18 gdt[n].seg_base_mid8 = (uint8)((((uint32)addr) >> 16) & 0xff); //段地址的中間8位
19 gdt[n].attr1 = 0x82; //該段在內存中存在,DPL=0,是LDT描述符
20 gdt[n].attr2_limit_high4 = 0x40; //段界限粒度是字節
21 gdt[n].seg_base_high8 = (uint8)((((uint32)addr) >> 24) & 0xff); //段地址的高8位
22 }
23
這兩個函數不長,代碼也很相似,他們完成的功能如下:
set_tss_seg()函數用于設置GDT中的某一描述符表項為指向進程控制塊中的tss的起始地址。
set_ldt_seg()函數用于設置GDT中的某一描述符表項為指向進程控制塊中的ldt的起始地址。
我們可以先預覽一下WinixJ的GDT表的樣子:
DUMMY
kernel-cs
kernel-ds
unused
process-0-tss
process-0-ldt
process-1-tss
process-1-ldt
process-2-tss
process-2-ldt
...
...
process-124-tss
process-124-ldt
unused
unused
其中每個GDT表項占用8字節,每個進程在gdt表中占用2項---1項是該進程的tss,1項是該進程的ldt。
ldtr寄存器中的值是ldt選擇子,即相對于GDT起始地址的偏移,據此它能索引到對應的ldt,進而取得對應的段基地址。
posted on 2012-02-14 17:30
myjfm 閱讀(453)
評論(0) 編輯 收藏 引用 所屬分類:
操作系統