1、系统物理地址空间可能没有实际地址空间大(即虚拟地址空间,由地址线长度决定)。虚拟内存是一种地址空间映射机制,它允许进程(运行的程序)不必完全加载到物理内存中也可以得到运行,进程操作的是虚拟地址。
2、虚拟内存与物理内存的映射关系由页表中的条目决定,MMU会根据进程号和进程所使用的虚拟内存自动转换到对应实际操作的物理空间。虚拟内存空闲页就通过链表一页一页串起来。
3、
每个链表的节点(DLIST_ELEMENT)保存:指向页帧属性的地址void *data;链表连接线*prev、*next
typedef struct _DLIST_ELEMENT
{
void *data;
struct _DLIST_ELEMENT *prev;
struct _DLIST_ELEMENT *next;
}DLIST_ELEMENT;
结构体DLIST_ATTRITIVE保存整个链表的属性
typedef struct _DLIST_ATTRITIVE
{
int size;
DLIST_ELEMENT *head;
DLIST_ELEMENT *tail;
void (*destroy)(void *data);
}DLIST_ATTRITIVE;
4、空闲页的插入和删除
//从空闲一串页中申请一页,即空闲页串删除一页
int alloc_frame(List *frames)
{
int frame_number, *data;
if(list_size(frames) == 0)
return -1;
else
{
if(list_rem_next(frames, NULL, (void **)&data) != 0)//删除链表节点
return -1;
else
{
frame_number = *data;//释放该节点指向的页内存
free(data);
}
}
return frame_number;
}
//还给空闲页串
int free_frame(List *frames, int frame_number)
{
int *data;
if((data = (int *)malloc(sizeof(int))) == NULL)
return -1;
*data = frame_number;
if(list_ins_next(frames, NULL, data) != 0)//在头部插入
return -1;
return 0;
}
5、一般情况下很多进程都可能在系统中同时运行,所有的进程都在争用物理内存,有时不得不替换某些页面到交换磁盘。交换哪个页面?
维护一个存在于物理内存中的页表的循环链表,链表中每个元素存储页码和一个索引值(*data指向的结构体)。所有页面的初始值设置为0,页面被操作就设置为1。找到第一个为0的页面交换到磁盘。找到的1把它设为0,继续向后找如果都是1循环到第一个从1设为0的页面。
指针data指向页面属性结构体Page
typedef struct _Page
{
int number;
int reference;
}Page;
int replace_page(ListElmt **current)
{
while(((Page *)(*current)->data)->reference != 0)
//如果索引值为1把它设为0,寻找下一个
{
((Page *)(*current)->data)->reference = 0;
*current = list_next(*current);
}
return ((Page*)(*current)->data)->number;
//返回第一个索引值为0的页面号,该页面放到交换空间
}