目錄
一、基本地址變換機構
二、地址變換過程
- 1)分頁地址變換機構將相對地址分爲(頁號,頁內地址)
- 頁號 P=INT[A/L];頁內位移量 W=A MOD L;
- 2)讀取PTR中的頁表長度。
- IF 頁號<頁表長度 THEN GOTO 3)ELSE 越界中斷;
- 3)讀取PTR中的頁表始址
- 計算:頁表始址+頁號×頁表項長度
- 得到該頁表項在頁表中的位置,對應得到該頁的物理塊號。裝入物理地址寄存器。
- 4)將邏輯地址中的頁內地址送入物理地址寄存器的塊內地址字段,拼接,得到最後的物理地址:塊號×塊長度+W
三、實驗內容
當進程在CPU上運行時,如指令中涉及邏輯地址時,操作系統自動根據頁長得到頁號和頁內偏移,把頁內偏移拷貝到物理地址寄存器,再根據頁號,查頁表,得到該頁在內存中的塊號,把塊號左移頁長的位數(二進制實現),寫到物理地址寄存器。
- 1、 設計頁表結構
- 2、 設計地址重定位算法
- 3、 有良好的人機對話界面
四、代碼實現
#include<stdio.h>
#include<stdlib.h>
#include<time.h> //封裝時間的類庫,時間不會重複,產生隨機數最合適
#define N 100 //設定的頁表最大長度爲100
#define True 1
#define False 0
int process; //進程大小
int Page_length; //頁長
int Page_Num; //頁表長度
int Logical_Address; //邏輯地址
int Physical_Address;//物理地址
int a[N]; //物理塊號集合
typedef struct PageTable //定義一個頁表項
{
int page_num; //頁號
int block_num; //對應的物理塊號
}PageTable;
PageTable PT[N]; //定義一個頁表
typedef struct LogicalAdd //定義邏輯地址
{
int page_num; //邏輯地址對應的頁號
int page_add; //對應的頁內地址
}LogicalAdd;
LogicalAdd LA;
/*****************輸入進程信息*****************/
void input()
{
printf("請輸入進程大小:" );
scanf("%d", &process);
printf("請輸入頁面大小:");
scanf("%d", &Page_length);
}
/*****************獲取到最小爲m,最大爲n,總數爲k個的不同隨機數*****************/
void get_rand(int m, int n, int k)//結果存在a數組中
{
/*-----srand(time(0))----- */
/*根據時間生成一個隨機數,僞隨機函數實現內存隨機分配,
srand函數就用來初始化這個發生器,
參數time(0)能夠生成從1970年1月1日到當前機器時間的秒數,
這個數在你每次執行程序的時候都會不斷增長、變化,
所以用它當做種子來初始化發生器,
每次運行程序時,頁號對應的塊號都會發生變化。*/
srand(time(0));
int i, j, t;
for(i = 0; i < k; )
{
/*rand()會返回一個範0~RAND_MAX(至少是32767)之間的僞隨機整數
採用"模除+加法"的方法,產生指定範圍內的隨機整數
在調用rand()函數之前,可以使用srand()函數設置隨機數種子,
如果沒有設置隨機數種子,rand()函數在調用時,自動設計隨機數種子。
隨機數種子相同,每次產生的隨機數也會相同。*/
t = rand() % (n-m+1) + m; //[m,n]
for(j = 0; j < i; j ++) //比較新生成的隨機數t與a[0]~a[i-1]
if(a[j] == t) break;
if(j == i)//不重複: j==i時,說明t與a數組中的數據(a[0]~a[i-1])不重複
a[i++] = t;//記錄隨機數。等價於a[i]=t; i++;
}
}
/*****************初始化函數,生成頁表*****************/
int init()
{
if(process % Page_length!=0)
Page_Num = process / Page_length + 1;
else
Page_Num = process / Page_length;
if(Page_Num > N)
{
printf("該進程的頁表長度爲%d,大於設定長度%d,無法存儲\n", Page_Num, N);
return False;
}
get_rand(0, N-1, Page_Num); //生成Page_Num個0~N-1的隨機數,存到數組a中
for (int i = 0; i < Page_Num; i++) //初始化頁表
{
PT[i].page_num = i;
PT[i].block_num = a[i]; //頁號對應的物理內存塊號
}
return True;
}
/*****************輸出頁表信息*****************/
void output( )
{
printf("\n");
printf("頁表長度爲:%d\n", Page_Num);
printf("構造的頁表如下:\n");
printf("\n");
printf("\t頁號\t塊號\n");
for (int i = 0; i < Page_Num; i++)
{
printf("\t %d\t",PT[i].page_num);
printf(" %d\n",PT[i].block_num);
}
printf("\n");
}
/*****************轉換函數,邏輯地址轉換爲物理地址*****************/
int translate()
{
printf("輸入邏輯地址:");
scanf("%d", &Logical_Address);
int i = 0;
LA.page_num = Logical_Address / Page_length;
LA.page_add = Logical_Address % Page_length;
if (LA.page_num >= Page_Num)
{
printf("所查詢的邏輯地址不在該頁內,轉換失敗\n");
return False;
}
while (i < Page_Num)
{
if (PT[i].page_num == LA.page_num) //找到頁表項
{
//找到LA.page_num對應的物理塊號PT[i].block_num
Physical_Address = PT[i].block_num * Page_length + LA.page_add;
printf("物理地址爲:%d\n", Physical_Address);
break;
}
else i++;
}
return True;
}
/*****************主函數*****************/
int main()
{
int choice;
printf("\t---------------------------------------------------\n");
printf("\t|| ||\n");
printf("\t|| 歡迎使用頁式地址重定位模擬系統 ||\n");
printf("\t|| ||\n");
printf("\t|| ||\n");
printf("\t|| 在此輸入個人姓名:****** ||\n");
printf("\t---------------------------------------------------\n");
for (;;)
{
printf("\t|| ||\n");
printf("\t|| 請選擇: ||\n");
printf("\t|| 1:重定位 2:退出 ||\n");
printf("\t|| ||\n");
printf("\t---------------------------------------------------\n");
scanf("%d", &choice);
switch (choice)
{
case 1:
input();
if (init() == False) return -1;
output();
translate();
break;
case 2:
printf("已經退出\n");
exit(0); //正常退出
default:
printf("輸入的值不合法,請重新輸入1或2\n");
}
}
return 0;
}
五、運行結果