时钟算法
计算机内存中,缓存是一种稀缺资源,虽然运行速度非常快,但是一个合理的算法能更好的提升性能.例如一个循环,在csapp一书中提到,是否合理的使用缓存的区域性.能影响两倍的性能.今天重点在页面置换的时钟算法不在这里过多描述.有兴趣的可以自行阅读,这个缓存区域性问题,在csapp中是很重视的.
算法数据结构描述
它就像一个时钟(顾名思义),但是却是一个只有时指针的时钟.刻度也是,没有分秒.但是这个时钟的移动却是为了寻找需要被替换的页面.
这里还有一个r 和w分别指,读写这个页面,它的写入我是没有做的,因为毕竟是描述这个算法.
工作方式
使用链表或者数组,但是我这里使用了链表.双向的.组成一个循环链表.每次寻找满足条件,r为为零就代表没有读过,也就是未使用,抛弃这个页面.如果为1就将这个页面置0,并指针向下移动.重复上述操作.直到找到满足条件.
结构体
typedef struct NODE { //页面
char read;
char write;
struct NODE *left;
struct NODE *right;
int date;
}node;
typedef struct CLOCK { //时钟结构体sd
int count; //时钟大小
node * ptr; //指针
node *root;
}clock;
全部实现
#include<stdio.h>
#include<stdlib.h>
#include<String.h>
typedef struct NODE { //页面
char read;
char write;
struct NODE *left;
struct NODE *right;
int date;
}node;
typedef struct CLOCK { //时钟结构体sd
int count; //时钟大小
node * ptr; //指针
node *root;
}clock;
void * Calloc(unsigned count , unsigned size);
node * readNode(node * n);
node *createnode(int size);
clock * init(int size);
node * position(node *root);
void moveNode(node * newNode, clock * cl);
void print(clock *cl);
node * newNode(int date);
//包装器
void *Calloc(unsigned count, unsigned size)
{
void *ptr = NULL;
if ((ptr = calloc(count, size)) == NULL) {
fprintf(stderr, "Calloc error!\n");
exit(-1);
}
else {
return ptr;
}
}
//通過驗證
node *createnode(int size)
{
node *root = NULL;
node *ptr = NULL;
int i = 0;
root = (node*)Calloc(1, sizeof(node));
root->date = 0;
ptr = root;
for (i = 1; i < size; i++) {
ptr->right = (node*)Calloc(1, sizeof(node));
ptr->right->left = ptr;
ptr->date = i;
ptr = ptr->right;
}
ptr->right = root;
root->left = ptr;
return root->left;
}
//初始化时钟
clock * init(int size) //通過
{
clock * root = (clock*)Calloc(1, sizeof(clock));
root->count = size;
root->root = createnode(size);
root->ptr = root->root;
return root;
}
//定位到符合条件的地方
node * position(node *root)
{
node *tmp = root;
while (1) {
if (tmp->read == 0) {
return tmp;
}
else {
tmp->read = 0;
}
tmp = tmp->right;
}
}
//页面置换
void moveNode(node * new_node, clock * cl)
{
node *ptr = position(cl->ptr);
new_node->left = ptr->left;
new_node->right = ptr->right;
ptr->right->left = new_node;
ptr->left->right = new_node;
cl->ptr = new_node->right;
if (ptr == cl->root) {
cl->root = new_node;
}
free(ptr);
}
//遍历时钟
void print(clock *cl)
{
node *ptr = cl->root;
node *ptrEnd = cl->root;
printf("%d \n", ptr->date);
ptr = ptr->right;
while (ptr != ptrEnd) {
printf("%d \n", ptr->date);
ptr = ptr->right;
}
}
//读数据
node * readNode(node * n)
{
n->read = 1;
return n;
}
//创建一个时钟节点
node * newNode(int date)
{
node * tmp = (node*)Calloc(1, sizeof(node));
tmp->date = date;
return tmp;
}
int main(void)
{
clock * cl = init(10);
node * tmp1 = newNode(20);
node * tmp2 = newNode(21);
node * tmp3 = newNode(22);
node * tmp4 = newNode(23);
node * tmp5 = newNode(24);
node * tmp6 = newNode(25);
node * tmp7 = newNode(26);
node * tmp8 = newNode(27);
print(cl);
moveNode(tmp1,cl);
printf("------------------------\n");
print(cl);
moveNode(tmp2, cl);
printf("------------------------\n");
print(cl);
moveNode(tmp3, cl);
printf("------------------------\n");
print(cl);
moveNode(tmp4, cl);
printf("------------------------\n");
print(cl);
moveNode(tmp5, cl);
printf("------------------------\n");
print(cl);
moveNode(tmp6, cl);
printf("------------------------\n");
print(cl);
moveNode(tmp7, cl);
moveNode(tmp8, cl);
printf("------------------------\n");
print(cl);
system("pause");
return 0;
}
这里因为篇幅已经很长了就不上运行结果.如果发现问题请帮忙指出.编写环境windows10 vs2017 如果是linux环境需要替换头文件,可以man查看.