**
【操作系统】基本分页和分段存储管理方式
**
参考文章:
基本分页:https://blog.csdn.net/qq_28602957/article/details/53588362
基本分段:https://blog.csdn.net/qq_28602957/article/details/53637103
**
基本分页存储管理方式
**
在分页存储管理方式中,如果不具备页面对换功能,不支持虚拟存储器功能,这种存储管理方式称为纯分页或基本分页存储管理方式。
在调度作业运行时,必须将它的所有页面一次调入内存,但逻辑上连续的各个页所对应的内存块可以不连续。
特殊的固定分区 + 离散分配
**
地址变换机构
**
地址变换机构
将用户地址空间中的逻辑地址变换为内存空间中的物理地址。
实现逻辑地址向物理地址的转换(页号 ⇒ 块号)
地址变换借助页表来完成。
地址变换机构种类
**
基本的地址变换机构
**
具有快表的地址变换机构
基本地址变换机构
地址变换借助页表来完成,页表驻留内存。
为了提高地址变换的速度,系统中设置一个页表寄存器PTR (Page-Table Register)。
每个进程对应一页表,其信息(如长度、始址)放在PCB 中,执行时将其装入页表寄存器。
在单处理机环境下,虽然系统中可以运行多个进程,但只需一个页表寄存器。
**
基本地址变换机构
**
当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分。
将页号与页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间,产生地址越界中断。
将页表始址与页号和页表项长度的乘积相加,得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。
将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。
逻辑地址: 把相对地址分为页号和页内地址两部分。
越界中断: 页号与页表长度做比较。
页表定位:页表始址 + 页号 × 页表项长度。{查询页表:读出块号。
物理地址:块号 + 块内地址。 (块内地址 = 页内地址)
**
地址变换例题
**
例:若在一分页存储管理系统中,某作业的页表如下表所示,已知页面大小为 1024B,试将十进制逻辑地址 1011,2148,5012 转化为相应的物理地址。
设页号为 P,页内位移为 W,逻辑地址为 A,内存地址为 M,页面大小为 L,则
P = int ( A / L )
W = A mod L
对于逻辑地址 1011
P=int(1011/1024)=0
W=1011 mod 1024=1011
A=1011=(0,1011)
查页表第 0 页在第 2 块,所以物理地址为 M=1024*2+1011= 3059。
对于逻辑地址为 2148
P= int (2148/1024)=2
W=2148 mod 1024=100
A=2148=(2,100)
查页表第 2 页在第 1 块,所以物理地
址为 M=1024*1+100=1124。
对于逻辑地址 5012
P= int ( 5012/1024)=4
W=5012 mod 1024=916
页号超过页表长度,该逻辑地址非法。
**
基本分段:
**
**
地址变换机构
**
系统将逻辑地址中的段号 S 与段表长度 TL 进行比较。
若 S>TL,表示段号太大,是访问越界,于是产生越界中断信号。
若未越界,则根据段表的始址和该段的段号,计算出该段对应段表项的位置,从中读出该段在内存的始址。
再检查段内地址 d,是否超过该段的段长 SL。
若超过,即 d >SL,同样发出越界中断信号。
若未越界,则将该段的基址与段内地址 d 相加,即可得到要访问的内存物理地址。
**
模拟基本分页算法(包括引入快表)和基本分段算法的简单代码实现:
**
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int home();//主页面(选择分页/分段)
void Pagination();//分页(选择基本分页/引入快表)
void Segmented();//基本分段
void basicPagination();//基本分页
void fastPagination();//引入快表
void fp(int w);//文件输入页表
void fp2();//文件输入段表
void basicPaginationtest(int n,int table[][2]);//基本分页算法
void fastPaginationtest(int n,int table[][2]);//基本分页引入快表算法
void maketable(int w);//手动输入页表
void makepiecewise();//手动输入段表
typedef struct piecewise{
//段表结构体
int piecewisenum;//段号
int piecewiselong;//段长
int piecewisefirst;//起始地址
int piecewisestate;//状态
}piecewise;
void Segmentedtest(int n,piecewise *p);//基本分段算法
//文件输入页表
void fp(int w){
//定义w是为了选择传入基本分页还是快表算法
int n,i;
int x,y;
FILE *fp;
//读取文件获得n
fp=fopen("test.txt","r");
for (n=0;!feof(fp);n++){
fscanf(fp,"%d %d",&x,&y);
}
fclose(fp);
//利用获得的n建表,不会浪费内存
int table[n][2];
//将文件写入表
fp=fopen("test.txt","r");
for (i=0;i<n;i++){
fscanf(fp,"%d %d",&x,&y);
table[i][0]=x;
table[i][1]=y;
}
fclose(fp);//关闭文件
//输出写入后的表
printf("读取到页表:\n");
for(i=0;i<n;i++){
printf("%d %d\n",table[i][0],table[i][1]);
}
if(w==1)basicPaginationtest(n,table);//基本分页
else fastPaginationtest(n,table);//引入快表
}
//文件输入段表
void fp2(){
int i,j,pieceNum;//pieceNum为对起始地址的转换,因为对起始地址用字符串读入,要转成int
FILE *fp;
int a,b,d,n;
char c[20]={
'\0'};
fp=fopen("test2.txt","r");
for (<