精华内容
下载资源
问答
  • 分页存储管理实验报告,实验报告,包含源码,结果,很详细的,不错
  • 存储管理提高型实验报告,包括实验目的和要求、实验条件、实验原理分析、实验方案或步骤、实验结果与分析,还有流程图和完整代码
  • 过简单的程序模拟两种存储管理算法,通过输入页面访问序列,查页表等操作判别是否缺页,按照FIFO和LRU两种算法淘汰页面,并调入所访问的页面,打印输入结果,在程序中,0代表为空,*代表缺页。 向管道中写入各自的...
  • 北邮计算机学院操作系统第二次实验-存储管理,包含源代码和运行结果截图
  • 模拟请求分页存储管理一、实验内容二、实验要求三、实验过程1、设计思想2、数据结构四、实验代码五、实验结果 一、实验内容 模拟请求分页存储管理方式。 二、实验要求 1、模拟请求分页存储管理方式,采用最近最久未...

    一、实验内容

    模拟请求分页存储管理方式。

    二、实验要求

    1、模拟请求分页存储管理方式,采用最近最久未使用替换算法;
    2、程序要添加适当的注释,程序的书写要采用缩进格式;
    3、程序要具在一定的健壮性,即当输入数据非法时,程序也能适当地做出反应;
    4、程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

    三、实验过程

    1、设计思想

    1. 设内存大小为4MB,页面大小为4KB。
    2. 立进程:由用户输入进程大小,随机数分配给进程页框数;
    3. 请求访问:
      [1] 由用户输入一个十进制的逻辑地址;
      [2] 如果页面已装入内存,通过地址变换机构计算其物理地址即可;
      [3] 如果页面未装入内存,查看分配的页框是否已经占满。若占满则使用最近最久未使用替换算法替换页面;若没有占满则直接将页面存入内存。
    4. 地址变换机构(十进制):
      [1] 由用户输入一个十进制的逻辑地址A;
      [2] 则页号为P=INT[A/L],页内地址为d=[A] MOD L,L为页面大小;
      [3] 查询页表,找到页号对应的物理块号B,计算物理地址B×L+d。
    5. 最近最久未使用替换算法:
      赋予每个页面一个访问字段,用于记录一个页面自上次被访问以来所经历的时间t。当需要淘汰一个页面时,选择所有页面中t值最大的予以淘汰。

    2、数据结构

    1.定义一个pcb类,表示每一个进程,含有进程的编号、大小、页表等信息:

    class PCB {
    private:
    	unsigned size;                        //进程大小
    	unsigned page_item_num;               //为进程分配的页框数
    	unsigned occu;                        //占用的页框数
    	unsigned length;                      //页表长度
    	vector<page_table_item> page_table;   //页表
    public:
    	void init(unsigned ps);                             //初始化
    	void disp();                                        //显示页表信息
    	bool comp(unsigned a);                              //越界检查
    	unsigned trans(unsigned a, vector<unsigned>& s);    //查询页表
    	void LRU(vector<page_table_item>::iterator p);      //LRU置换算法
    };
    

    2.对于每一个页表项,建立类page_table_item,包含访问为、状态位等信息:

    class page_table_item {
    public:
    	page_table_item() {
    		chunk_no = NULL;
    		state = 0;
    		visit = 0;	
    	}
    public:
    	unsigned chunk_no;   //物理块号
    	bool state;          //状态位,1表示已调入内存
    	unsigned visit;      //访问位
    };
    

    四、实验代码

    pcb.h

    #include<vector>
    
    using namespace std;
    
    class page_table_item {
    public:
    	page_table_item() {
    		chunk_no = NULL;
    		state = 0;
    		visit = 0;	
    	}
    public:
    	unsigned chunk_no;   //物理块号
    	bool state;          //状态位,1表示已调入内存
    	unsigned visit;      //访问位
    };
    
    class PCB {
    private:
    	unsigned size;                        //进程大小
    	unsigned page_item_num;               //为进程分配的页框数
    	unsigned occu;                        //占用的页框数
    	unsigned length;                      //页表长度
    	vector<page_table_item> page_table;   //页表
    public:
    	void init(unsigned ps);               //初始化
    	void disp();                          //显示页表信息
    	bool comp(unsigned a);                              //越界检查
    	unsigned trans(unsigned a, vector<unsigned>& s);    //查询页表
    	void LRU(vector<page_table_item>::iterator p);      //LRU置换算法
    };
    

    pcb.cpp

    #include"pcb.h"
    #include<ctime>
    #include<random>
    #include<cmath>
    #include<iostream>
    
    using namespace std;
    
    //初始化PCB
    void PCB::init(unsigned ps) {
    	size = ps;
    	uniform_int_distribution<unsigned> u(3, 5);
    	default_random_engine e(time(0));
    	page_item_num = u(e);
    	cout << "为进程分配的页框数为:" << page_item_num << endl;
    	occu = 0;
    	length = size / 4;
    	if (size % 4 != 0)
    		length++;
    	for (unsigned i = 0; i < length; i++) {
    		page_table.push_back(page_table_item());
    	}
    }
    
    //显示页表信息
    void PCB::disp() {
    	int no = 0;
    	auto i = page_table.begin();
    	cout << "页号" << "\t" << "物理块号" << "\t"
    		<< "状态位" << "\t" << "访问字段" << "\t" << endl;
    	while (i != page_table.end()) {
    		if (i->state == 1) {
    			cout << no << "\t" << i->chunk_no << "\t\t"
    			<< i->state << "\t" << i->visit << "\t\t" << endl;
    		}
    		no++;
    		i++;
    	}
    }
    
    //越界检查
    bool PCB::comp(unsigned a) {
    	if (a >= length || a < 0)
    		return 1;
    	else
    		return 0;
    }
    
    //查询页表
    unsigned PCB::trans(unsigned a, vector<unsigned>& s) {
    	auto p = page_table.begin();
    	unsigned no,flag=0;
    	uniform_int_distribution<unsigned> u(0, unsigned(pow(2, 10.0)));
    	default_random_engine e(time(0));
    	for (unsigned i = 0; i < a; i++) {
    		p++;
    	}
    	//页在内存中
    	if (p->state == 1) {
    		return p->chunk_no;
    	}
    	//页不在内存中
    	if (occu < page_item_num) {
    		p->state = 1;
    		for (auto i = page_table.begin(); i != page_table.end(); i++) {
    			i->visit++;
    		}
    		p->visit=0;
    		no = u(e);
    		while (!flag) {
    			for (auto q = s.begin(); q != s.end(); q++) {
    			    if (*q == no) 
    					flag = 1;
    				break;
    			}
    			if (!flag) {
    				p->chunk_no = no;
    				s.push_back(no);
    				flag = 1;
    			}
    			else {
    				no++;
    				flag = 0;
    			}
    		}
    		occu++;
    	}
    	else if (occu >= page_item_num) {
    		LRU(p);		
    	}
    	return p->chunk_no;
    }
    
    void PCB::LRU(vector<page_table_item>::iterator p) {
    	auto q = page_table.begin();
    	while (q->state != 1) {
    		q++;
    	}
    	auto index = q;
    	while (q != page_table.end()) {
    		if(q->visit>index->visit&&q->state==1){//找到访问值最大的
    			index = q;
    		}
    		q++;
    	}
    	p->state = 1;
    	index->state = 0;
    	p->chunk_no = index->chunk_no;
    	index->chunk_no = NULL;
    	for (auto i = page_table.begin(); i != page_table.end(); i++) {
    		i->visit++;
    	}
    	p->visit = 0;
    }
    

    exp7.cpp

    #include"pcb.h"
    #include<iostream>
    #include<cmath>
    #include<string>
    
    using namespace std;
    
    //内存大小4MB,页面大小4KB
    //创建进程
    bool create(PCB& p) {
    	unsigned psize;
    	cout << "请输入进程大小(KB):";
    	cin >> psize;
    	p.init(psize); //初始化
    	return 0;
    }
    
    //地址转换机构
    void addr_trans(PCB& pro, vector<unsigned>& s) {
    	unsigned addr;
    	unsigned page_no, offset;
    	cout << "输入十进制地址:";
    	cin >> addr;
    	page_no = unsigned(addr / 4096);
    	//进行越界检查
    	while (pro.comp(page_no)) {
    		cout << "地址越界,重新输入十进制地址:";
    		cin >> addr;
    		page_no = unsigned(addr / 4096);
    	}
    	offset = unsigned(addr % 4096);
    	//访问页表
    	cout << "物理地址为:" << pro.trans(page_no, s) * 4096 + offset << endl;
    }
    
    int main() {
    	int choose = 0;
    	PCB pro;
    	vector<unsigned> s;   //记录占用的物理块号
    	cout << "1.创建进程\n"
    		<< "2.显示进程页表\n"
    		<< "3.请求访问\n"
    		<< "4.退出" << endl;
    	while (choose != 4) {
    		cout << "\n请选择:";
    		cin >> choose;
    		switch (choose) {
    		case 1:
    			if (create(pro))
    				cout << "创建失败!" << endl;
    			else
    				cout << "创建成功!" << endl;
    			break;
    		case 2:
    			pro.disp();
    			break;
    		case 3:
    			addr_trans(pro, s);
    			break;
    		default:
    			break;
    		}
    	}
    	return 0;
    }
    

    五、实验结果

    实验结果

    展开全文
  • 基本分页存储管理一、实验内容及要求二、实验环境三、设计思想四、数据结构五、实验代码六、运行结果 一、实验内容及要求 模拟分页存储管理方式; 模拟分页存储管理方式,定义地址变换机构函数; 程序要添加适当的...

    注:其他实验见:点击查看

    一、实验内容及要求

    1. 模拟分页存储管理方式;
    2. 模拟分页存储管理方式,定义地址变换机构函数;
    3. 程序要添加适当的注释,程序的书写要采用缩进格式;
    4. 程序要具在一定的健壮性,即当输入数据非法时,程序也能适当地做出反应;
    5. 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

    二、实验环境

    windows 10,Visual Studio 2019

    三、设计思想

    1. 设内存大小为2GB,页面大小为4KB。
    2. 建立进程:由用户输入进程ID与大小,随机数分配各个页面对应的物理块号;
    3. 地址变换(十进制):
      [1] 由用户输入一个十进制的逻辑地址A;
      [2] 则页号为P=INT[A/L],页内地址为d=[A] MOD L,L为页面大小(4096);
      [3] 查询页表,找到页号对应的物理块号B,计算物理地址B×L+d。
    4. 地址变换(二进制):
      [1] 由用户输入一个二进制的逻辑地址A;
      [2] 设页内地址的位数为x,则页号为A>>x,页内地址为A的低x位;
      [3] 查询页表,找到页号对应的物理块号,计算物理地址将物理块号与页内地址拼接即可。

    四、数据结构

    1. 定义一个pcb类,表示每一个进程,含有进程的编号、大小、页表等信息:
    class PCB {
    public:
    	PCB(int a, int b) :id(a), size(b) {};
    private:
    	int id;                   //进程编号
    	int size;                 //进程大小
    	int length;               //页表长度
    	vector<int> page_table;   //页表
    public:
    	void init(vector<int> &s);       //给每页分配相应的物理块号
    	void disp();                     //显示页表信息
    	int comp(int a,int b);           //越界检查
    	int comp(bitset<31> a, int b);   //越界检查
    	int trans(int a);                //查询页表
    	int trans(bitset<31> a);         //查询页表
    };
    
    1. 对于二进制的处理,使用bitset<31>结构来进行相关的逻辑移位、按位与或运算、转换成十进制等。

    五、实验代码

    #include<vector>
    #include<bitset>
    #include<ctime>
    #include<random>
    #include<cmath>
    #include<iostream>
    #include<string>
    
    using namespace std;
    
    class PCB {
    public:
    	PCB(int a, int b) :id(a), size(b) {};
    private:
    	int id;                   //进程编号
    	int size;                 //进程大小
    	int length;               //页表长度
    	vector<int> page_table;   //页表
    public:
    	void init(vector<int> &s);       //给每页分配相应的物理块号
    	void disp();                     //显示页表信息
    	int comp(int a,int b);           //越界检查
    	int comp(bitset<31> a, int b);   //越界检查
    	int trans(int a);                //查询页表
    	int trans(bitset<31> a);         //查询页表
    };
    
    //给每页分配相应的物理块号
    void PCB::init(vector<int> &s) {
    	int num,a,flag=1;
    	num = size / 4;
    	if (size % 4 != 0) {
    		num++;
    	}
    	static uniform_int_distribution<int> u(0, int(pow(2,19)));
    	static default_random_engine e(time(0));
    	while(page_table.size()!=num) {
    		a = u(e);
    		for (auto j = s.begin(); j != s.end(); j++) {    //检查物理块是否被占用
    			if (*j == a) {
    				flag = 0;
    				break;
    			}
    		}
    		if (flag) {
    			page_table.push_back(a);
    			s.push_back(a);
    		}
    	}
    	length = page_table.size();
    }
    
    //显示页表信息
    void PCB::disp() {
    	int no=0;
    	auto i = page_table.begin();
    	while (i != page_table.end()) {
    		cout << no << "\t" << *i << endl;
    		no++;
    		i++;
    	} 
    }
    
    //越界检查
    int PCB::comp(int a,int b) {
    	if (id!=b)
    		return 1;
    	else if (a > length|| a < 0)
    		return 2;
    	else
    		return 0;
    }
    
    //越界检查
    int PCB::comp(bitset<31> a, int b) {
    	if (id != b)
    		return 1;
    	else if (a.to_ulong() > length - 1 || a.to_ulong() < 0)
    		return 2;
    	else
    		return 0;
    }
    
    //查询页表
    int PCB::trans(int a) {
    	auto p = page_table.begin();
    	for (int i = 0; i < a; i++) {
    		p++;
    	}
    	return *p;
    }
    
    //查询页表
    int PCB::trans(bitset<31> a) {
    	auto p = page_table.begin();
    	for (int i = 0; i < int(a.to_ulong()); i++) {
    		p++;
    	}
    	return *p;
    }
    
    //内存大小2GB,页面大小4KB
    //创建进程
    bool create(vector<PCB>& pcbs, vector<int>& s) {
    	unsigned pid,psize;
    	cout << "请输入进程编号与大小(KB):";
    	cin >> pid >> psize;
    	if (psize > (524288 - s.size()) * 4) {
    		return 1;
    	}
    	pcbs.push_back(PCB(pid, psize));
    	auto p = pcbs.end();
    	p--;
    	p->init(s);
    	return 0;
    }
    
    //显示页表
    void display(vector<PCB> pcbs) {
    	int num=1;
    	for (auto i = pcbs.begin(); i != pcbs.end(); i++) {
    		cout << "第" << num << "个进程:" << endl;
    		cout << "页号\t" << "块号" << endl;
    		i->disp();
    		num++;
    	}
    }
    
    //地址转换机构1
    bool addr_trans(vector<PCB> pcbs) {
    	int no,addr;
    	int chunk_no,offset;
    	auto p = pcbs.begin();
    	cout << "输入转换的进程编号:";
    	cin >> no;
    	cout << "输入十进制地址:";
    	cin >> addr;
    	chunk_no = addr / 4096;
    	//找到进程并进行越界检查
    	while (p!=pcbs.end()&&p->comp(chunk_no, no)) {
    		if (p->comp(chunk_no, no) == 1)
    			p++;
    		else if (p->comp(chunk_no, no) == 2) {
    			cout << "地址越界,重新输入十进制地址:";
    			cin >> addr;
    			chunk_no = addr / 4096;
    		}	
    	}
    	if (p == pcbs.end()) {
    		cout << "未找到该进程!";
    		return 1;
    	}
    	offset = addr % 4096;
    	cout << "对应的物理地址为:" << p->trans(chunk_no)*int(pow(2,12.0)) + offset << endl;
    	return 0;
    }
    
    //地址变换机构2
    bool addr_trans2(vector<PCB> pcbs) {
    	bitset<31> addr,chunk_no, offset, s(string("0000000000000000000111111111111"));
    	bitset<31> p_addr;
    	int no;
    	auto p = pcbs.begin();
    	cout << "输入转换的进程编号:";
    	cin >> no;
    	cout << "输入二进制地址:";
    	cin >> addr;
    	chunk_no = addr >> 12;
    	//找到进程并进行越界检查
    	while (p != pcbs.end()&&p->comp(chunk_no, no)) {
    		if (p->comp(chunk_no, no) == 1)
    			p++;
    		else if (p->comp(chunk_no, no) == 2) {
    			cout << "地址越界,重新输入十进制地址:";
    			cin >> addr;
    			chunk_no = addr >> 12;
    		}
    	}
    	if (p == pcbs.end()) {
    		cout << "未找到该进程!";
    		return 1;
    	}
    	offset = addr & s;
    	p_addr = p->trans(chunk_no);
    	p_addr = p_addr << 12;
    	p_addr = p_addr | offset;
    	cout << "对应的二进制物理地址为:" << p_addr 
    		<< "\n转化为十进制为:" << p_addr.to_ulong()
    		<< endl;
    	return 0;
    }
    
    int main() {
    	int choose = 0;
    	vector<PCB> pcbs;
    	vector<int> s;   //记录占用的物理块号
    	cout << "1.创建进程\n"
    		<< "2.显示进程页表\n"
    		<< "3.逻辑地址转换(十进制)\n"
    		<< "4.逻辑地址转换(二进制)\n"
    		<< "5.退出" << endl;
    	while (choose != 5) {
    		cout << "\n请选择:" ;
    		cin >> choose;
    		switch (choose) {
    		case 1:
    			if (create(pcbs,s))
    				cout << "创建失败!" << endl;
    			else
    				cout << "创建成功!" << endl;
    			break;
    		case 2:
    			display(pcbs);
    			break;
    		case 3:
    			if (addr_trans(pcbs)) {
    				cout << "转换失败!" << endl;
    			};
    			break;
    		case 4:
    			if (addr_trans2(pcbs)) {
    				cout << "转换失败!" << endl;
    			};
    			break;
    		default:
    			break;
    		}
    	}
    	return 0;
    }
    
    

    六、运行结果

    运行结果

    展开全文
  • 处理find命令查找出来的结果Linux中的高级存储管理实验环境准备1.逻辑卷LVM设备建立分区建立物理卷建立大小为200M的逻辑卷格式化拉伸2.当vg中的容量不足xfs文件系统ext4文件系统拉伸缩减转移数据LVM建立快照LVM设备...

    Linux中的高级存储管理

    基本存储管理之find

    find:设备中文件的查找

    实验环境准备

    id westos
    id root
    id lee
    useradd lee
    id lee
    cd /mnt/
    ls
    rm -fr *
    ls
    touch westosfile{1..5}
    ll
    cd /mnt/
    chmod 000 westosfile*
    ll
    chown lee westosfile1
    chgrp westos westosfile2
    chown westos.lee westosfile3
    chmod ug+w westosfile1
    chmod ugo+w westosfile2
    chmod 755 westosfile3
    chmod 666 westosfile4
    chmod 700 westosfile5
    mkdir westosdir
    ls -l /mnt/
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    1.用文件名字的方式

    find -name
    find /mnt -name westosfile1
    find /mnt -name westos*
    

    在这里插入图片描述

    2.设定类型

    find -type f d s b l
    find /mnt -type d
    

    3.设定深度

    find -maxdepth 1
    find -mindepth 1
    find /mnt -maxdepth 1 -type d
    find /mnt -maxdepth 2 -type d
    ##最大深度
    find /mnt -mindepth 2 -type d
    find /mnt -mindepth 1 -type d
    find /mnt -mindepth 0 -type d
    ##最浅深度
    find /etc/ -name passwd
    find /etc/ -maxdepth 1 -name passwd
    find /etc/ -maxdepth 2 -name passwd
    

    在这里插入图片描述

    4.用户方式

    find -user
    find /mnt -user root
    

    在这里插入图片描述

    5.组方式

    find -group
    find /mnt -group westos
    ##用户方式和组方式(并)
    find /mnt -user westos -a -group lee
    ##用户方式和组方式(或)
    find /mnt -user westos -o -group lee
    find /mnt -user root -o -group lee
    

    在这里插入图片描述

    6.反向选择

    find -not
    find /mnt -not -user root -o -group lee
    

    在这里插入图片描述

    7.在某时间内被修改过的文件

    find -cmin 1 -1 +1
    date
    touch /mnt/westosfile3
    find /mnt -cmin -1
    find /mnt -cmin +1
    find /mnt -cmin 1
    date
    find /mnt -cmin 1
    

    在这里插入图片描述
    在这里插入图片描述

    8.以文件容量对文件进行查找

    find -size +|-| 1M
    dd ##截取指令大小的文件
    dd if=/dev/zero of=/mnt/westosfile1 bs=1M count=10
    dd if=/dev/zero of=/mnt/westosfile2 bs=1M count=20
    dd if=/dev/zero of=/mnt/westosfile3 bs=1M count=30
    find /mnt -size 20M
    find /mnt -size -20M
    find /mnt -size +20M
    

    在这里插入图片描述
    在这里插入图片描述

    9.以权限查找

    find -perm 222 /222 -222
    find /mnt -perm 222
    ##指定权限位查找(精确,包含关系)
    find /mnt -perm /222
    ##文件权限位u/g/o其中有一个权限位的写权限打开(或)
    find /mnt -perm -222
    find /mnt -perm -002
    ##文件权限位u/g/o权限位必须都要打开写权限(并)
    ##企业七之前需要“+”,企业八优化后为“-”
    

    在这里插入图片描述

    10.处理find命令查找出来的结果

    非shell命令中的分号,而是find命令中的分号

    find -exec
    find /mnt -perm -002 -exec rm -fr {} \;
    

    在这里插入图片描述

    Linux中的高级存储管理

    实验环境准备

    全新的虚拟机
    添加一块硬盘(关闭虚拟机状态下)
    在这里插入图片描述
    在这里插入图片描述

    fdisk -l
    ifconfig
    cd /etc/sysconfig/network-scripts/
    vim ifcfg-enp1s0
    nmcli connection reload
    ifconfig
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    当我们的数据目录被用户数据填满时如何解决此问题?
    需求: 在原有数据不变的情况下,把设备内存变大。
    在部署设备时,需要接入一个可以拉伸的存储设备。

    解决:逻辑卷
    功能:用软件的方式,管理我们的存储。
    相当于“胶水”,将物理设备连接起来(用软件的方式连接)
    物理卷pv————>叠放在一起————>物理卷组vg————>划分出可用的组织————>包含许多物理扩展————>划分组成逻辑卷lv

    1.逻辑卷

    pv ##物理卷,被处理过的物理分区
    pe ##物理扩展,设定存储最小单元
    vg ##物理卷组,捆绑pv到一个组中
    lv ##逻辑卷,分配最终的使用设备

    加装监控:
    watch -n 1 "pvs;echo ====;vgs;echo ====;df -h /weixindata"
    

    在这里插入图片描述

    LVM设备建立

    分区

    fdisk /dev/vdb
    ##修改分区类型
    ##指定被修改的分区id
    ##列出所有分区类型代码
    ##LVM 分区类型
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    建立物理卷

    在这里插入图片描述

    mkdir /weixindata
    fdisk /dev/vdb
    ##建立物理卷组
    pvcreate /dev/vdb1
    pvcreate /dev/vdb2
    ##创建pv
    vgcreate -s 2M westos_vg /dev/vdb1
    ##查看物理卷大小(默认为4GB)
    ##创建vg,-s指定物理卷pe大小为2GB
    

    在这里插入图片描述
    在这里插入图片描述

    建立大小为200M的逻辑卷

    lvcreate -L 200M -n westos_lv0 westos_vg
    ##创建lvm,-L指定大小,-n指定名称
    

    格式化

    mkfs.xfs /dev/westos_vg/westos_lv0
    ##格式化
    mount /dev/westos_vg/westos_lv0 /weixindata/
    ##挂载逻辑卷
    ##1M=1024k(10的n次方,更方便)=1000k(2的n次方,更精确)
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    拉伸

    lvm热拉神:不够随时拉大

    lvextend -L 200M /dev/mapper/westosvg-westoslv
    ##拉伸设备
    xfs_growfs /weixindata/
    ##拉伸文件系统,在rhel7中可以用设备或挂载点
    ##在rhel8.0中只能用挂载点
    resize2fs /dev/mapper/westos-westoslv 
    ##当文件系统为ext时使用此命令
    

    2.当vg中的容量不足

    xfs文件系统

    xfs文件系统:
    只支持拉伸不支持缩减
    设备拉大
    文件系统拉大

    blkid
    lvextend -L 400M /dev/westos_vg/westos_lv0
    xfs_growfs /dev/westos_vg/westos_lv0
    拉伸vg组
    vgextend westos_vg /dev/vdb2
    拉伸设备
    lvextend -L 600M /dev/westos_vg/westos_lv0
    拉伸文件系统
    xfs_growfs /dev/westos_vg/westos_lv0
    

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    ext4文件系统

    拉伸

    umount /weixindata
    mkfs.ext4 /dev/westos_vg/westos_lv0
    ##卸载原有文件系统
    ##格式化文件系统类型为ext4
    mount /dev/westos_vg/westos_lv0 /weixindata/
    ##挂载文件系统到/weixindata/
    ##(文件系统拉伸的方式不同)
    lvextend -L 800M /dev/westos_vg/westos_lv0
    ##拉伸到800M
    

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    缩减

    umount /weixindata
    ##卸载设备
    resize2fs /dev/westos_vg/westos_lv0
    e2fsck -f /dev/westos_vg/westos_lv0
    ##扫描检测文件系统中的数据大小
    resize2fs /dev/westos_vg/westos_lv0 200M
    ##先缩减文件系统
    mount /dev/westos_vg/westos_lv0 /weixindata/
    ##挂载设备
    lvreduce -L 200M /dev/westos_vg/westos_lv0
    ##再缩减设备
    

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    转移数据

    pvmove /dev/vdb1 /dev/vdb2
    ##将vdb1的数据移动到vdb2上
    ##缩减vg时,要先确定有一块空闲的硬盘
    vgreduce westos_vg /dev/vdb1
    ##删除vg组
    pvremove /dev/vdb1
    ##移除硬盘
    

    在这里插入图片描述

    LVM建立快照

    cd /weixindata/
    ls
    touch westosfile
    echo hello westos > westosfile
    cat westosfile
    cd
    umount /weixindata
    cat /weixindata/westosfile
    lvcreate -L 30M -n westos_lv0_backup -s /dev/westos_vg/westos_lv0
    ##相当于将设备reset
    mount /dev/westos_vg/westos_lv0_backup /weixindata/
    cat /weixindata/westosfile
    

    在这里插入图片描述
    在这里插入图片描述

    LVM设备的删除

    umount /weixindata
    ##删除设备
    lvremove /dev/westos_vg/westos_lv0_backup
    ##删除快照
    lvremove /dev/westos_vg/westos_lv0
    ##删除原始设备
    vgremove westos_vg
    ##删除vg
    pvremove /dev/vdb2
    ##删除pv
    

    在这里插入图片描述

    vdo(Virtual Data Optimize)

    vdo 虚拟数据优化器

    kvdo
    ##压缩数据 uds
    ##优化重复数据

    1.vdo设备的建立

    实验准备

    mkdir /weixindata
    watch -n 1 "pvs;echo ====;vgs;echo ====;df -h /weixindata"
    

    安装vdo软件

    dnf install vdo -y
    

    确保设备未被利用

    将做实验的设备的前1M分区表清空,破坏分区表
    初始化设备未利用

    lsblk
    ##查看设备使用情况
    pvs
    fdisk /dev/vdb
    dd if=/dev/zero of=/dev/vdb bs=1M count=1
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    扩充内存

    扩充内存到2GB=2048MiB
    在这里插入图片描述
    在这里插入图片描述

    手动设定运行级别

    init 3 
    ##无图形界面,减少内存消耗
    

    查看帮助

    vdo --help
    

    vdo建立

    在这里插入图片描述

    vdo create --name=westos_vdo1 --device=/dev/vdb
    vdo status --name=westos_vdo1 | less
    Deduplication: enabled
    ##vdo检测并删除重复数据的功能时开启的
    Compression: enabled
    ##vdo数据压缩功能开启
    

    在这里插入图片描述
    在这里插入图片描述

    使用vdo设备

    mkfs.xfs /dev/mapper/westos_vdo1
    mount /dev/mapper/westos_vdo1 /weixindata/
    df -H
    df
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.vdo性能检测

    在这里插入图片描述
    在这里插入图片描述

    find / -size +100M
    du -sh /usr/lib64/firefox/libxul.so
    cp /usr/lib64/firefox/libxul.so /weixindata/
    cp /usr/lib64/firefox/libxul.so /weixindata/westos1
    cp /usr/lib64/firefox/libxul.so /weixindata/westos3
    cd /weixindata/
    ls
    ll
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.vdo自动挂载

    vdo create --name=westos_vdo1 --device=/dev/vdb
    watch -n 1 vdostats --human-readable
    vim /etc/fstab
    systemctl status vdo
    reboot
    vim /etc/fstab
    ##实现开机自动挂载
    ##注意需要添加参数,否则设备起不来
    reboot
    df
    umount /weixindata
    vim /etc/fstab
    vdo remove --name=westos_vdo1
    ##vdo设备的删除
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    /dev/mapper/vdodevice /westos xfs defaults,x-systemd.requires=vdo.service 0 0
    
    展开全文
  • 可变分区存储管理

    2011-11-23 21:15:47
    操作系统实验: 可变分区存储管理 包括算法原理、程序流程图、源代码、运行结果
  • 目录进程调度目的和要求内容与步骤运行结果问题及心得C语言实现代码存储管理目的和要求内容与步骤运行结果问题及心得C语言实现代码死锁避免银行家算法目的和要求内容与步骤运行结果问题及心得C语言实现关键代码 ...

    **皮卡皮卡丘~~~~~~**

    进程调度

    目的和要求

    编写并调试一个模拟的进程调度程序,采用“最高优先数优先”调度算法对五个进程进行调度,以加深对进程的概念及进程调度算法的理解。

    内容与步骤

    设计一个有 N 个进程共行的进程调度程序。
    **进程调度算法:**采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用 CPU 时间、进程状态等等。进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生),进程的到达时间为进程输入的时间,进程的运行时间以时间片为单位进行计算。每个进程的状态可以是就绪 W(Wait)、运行 R(Run)、或完成 F(Finish)三种状态之一(这是编程用到的三个模拟状态,并非进程的三基态)。就绪进程获得 CPU 后都只能运行一个时间片,用
    已占用 CPU 时间加 1 来表示。如果运行一个时间片后,进程的已占用 CPU 时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用 CPU 时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减 1(即降低一级),然后把它插入就绪队列等待 CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。
    调度算法的流程图如下 :
    在这里插入图片描述
    HTML代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <style>
        .hid{
            display: none;
        }
        .appear{
            display: block;
        }
        span{
            margin-left: 50px;
        }
        .name{
            width: 70px;
            margin-left: 40px;
        }
        .super{
            width: 70px;
            margin-left: 30px;
        }
        .totaltime{
            width: 70px;
            margin-left: 30px;
        }
        .ok{
            margin-top: 30px;
        }
        #Waiting span,#Running span{
            margin-right: 40px;
        }
        .im-com{
            width:600px;
            height:350px;
            background:url(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1558862265029&di=844ed2dec44eb9014a3450e13e3bbb7c&imgtype=0&src=http%3A%2F%2Fs10.sinaimg.cn%2Fmiddle%2F00378002g7a90910f4dc9%26690) no-repeat top left scroll;
            background-size:cover;
        }
        p{
            color:mediumpurple;
            font-family: STXingkai;
        }
        input{
            text-align: center;
            border-radius: 10px;
            background: transparent;
    
        }
    
    </style>
    <style type="text/css">
        #sure,#ok,#biggest{width: 50px;height: 50px;border-radius: 50%;border: none}
        /* border-radius */
    </style>
    
    <body>
    <div class="im-com">
        <h1 align="center"><font color="#ffc0cb">进程调度</font></h1>
    <div id="super" style="text-align:center; vertical-align:middle;">
        <big>
        <div id="box1">
            <p align="center">请输入进程号个数</p>
            <input    type="text" id="number"  title="num"/>
            <button  type="button" id="sure" style="background:skyblue">sure</button>
       </div>
        </big>
    </div>
    
        <div id="box2" class="hid">
            <p align="center">请输入进程信息</p>
            <p>
                <span>进程名</span>
                <span>进程优先级</span>
                <span>进程运行时间</span>
            </p>
            <div id="input"></div>
            <button type="button" id="ok" class="ok" style="background:skyblue;margin-left: 140px">sure</button>
        </div>
    
    
    
    
        <div id="resultbox" class="hid">
            <p align="center">programming result</p>
            <p align="center">当前运行进程</p>
            <span>进程名</span><span>程序状态</span><span>优先级</span><span>需要时长</span><span>已运行时长</span>
            <div id="Running">
                当前没有运行中的队列
            </div>
            <p align="center">就绪队列</p>
            <span>进程名</span><span>程序状态</span><span>优先级</span><span>需要时长</span><span>已用时间</span>
            <div id="Waiting">
    
            </div>
            <br /><br />
            <button type="button" id="biggest" style="background:skyblue;margin-left: 174px">最高优先数优先</button>
        </div>
    </div>
    
    <script type="text/javascript" src="jincheng.js"></script>
    </body>
    </html>
    

    JS代码

    charset='utf-8';
    console.log("*********  js   ***********");
    
    let num_inp = document.getElementById("number");
    let num;
    let input=document.getElementById("input");
    let btn = document.getElementById("sure");
    let ready = [];
    let ok = document.getElementsByClassName("ok")[0];
    let biggest = document.getElementById("biggest");
    let Running = document.getElementById("Running");
    let Waiting = document.getElementById("Waiting");
    
    let box1 = document.getElementById("box1"),
        box2 = document.getElementById("box2"),
        resultbox = document.getElementById("resultbox");
    
    btn.onclick = function(){//创建输入框
        num = num_inp.value;
        console.log(num);
        let INNER="";
        for(let i=0;i<num;i++){
            INNER +=`<div>
                        <input title="inf" class="name">
                        <input title="inf" class="super">
                        <input title="inf" class="totaltime">
                      </div>`;
        }
        input.innerHTML = INNER;
        box1.className = "hid";
        box2.classList.remove("hid");
    };
    
    ok.onclick = function () {//获取输入框的值
    
        let names=document.getElementsByClassName("name"),
            supers = document.getElementsByClassName("super"),
            totaltimes=document.getElementsByClassName("totaltime");
    
        for(let i=0;i<num;i++){
            let m = {
                name: names[i].value,
                super: supers[i].value,
                state: "w",
                ntime: totaltimes[i].value,
                rtime: 0
            };
            ready.push(m);
        }
        // Sort();
        console.log(ready);
        let W = "";
        for (let i = 0; i < ready.length; i++) {
            W+=`
                <p>
                    <span>`+ready[i].name+`</span><span>Waiting</span><span>`+ready[i].super+`</span><span>`+ready[i].ntime+`</span><span>`+ready[i].rtime+`</span>
                </p>
            `;
        }
        Waiting.innerHTML = W;
        box2.className = "hid";
        resultbox.classList.remove("hid");
    };
    
    
    function Sort() {
        function compare(property){
            return function(a,b){
                let value1 = a[property];
                let value2 = b[property];
                return value2 - value1;
            }
        }
        ready.sort(compare('super'));
        console.log(ready);
    }
    
    biggest.onclick = function() {//点击下一步
        if (ready.length===0){
            alert("全部完成");
            return 0;
        } else {
            RunSuper();
        }
    };
    
    function RunSuper() {
        ready[0].state="running";
        ready[0].super--;
        ready[0].rtime++;
        disp();
        let t = ready[0];
        ready.splice(0,1);
        if(t.rtime != t.ntime){
            ready.push(t);
        }
    }
    
    function disp() {
        let R = `<p>
                    <span>`+ready[0].name+`</span><span>Running</span><span>`+ready[0].super+`</span><span>`+ready[0].ntime+`</span><span>`+ready[0].rtime+`</span>
                </p>`;
        Running.innerHTML = R;
        let W = "";
        for (let i = 0; i < ready.length - 1; i++) {
            W+=`
                <p>
                    <span>`+ready[i+1].name+`</span><span>Waiting</span><span>`+ready[i+1].super+`</span><span>`+ready[i+1].ntime+`</span><span>`+ready[i+1].rtime+`</span>
                </p>
            `;
        }
        Waiting.innerHTML = W;
    }
    

    运行结果

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    问题及心得

    通过此次实验,了解了进程调度相关的知识,这次实验采用的是最高优先数优先算法,即把 CPU 分配给就绪队列中优先数最高的进程,而其中所用的静态优先数是在创建进程时确定的,并在整个进程运行期间不再改变。所选用的图形界面是用web所显示出来,通过网页w3school自学了HTML的相关知识,懂得了相关的基本操作,编写了js代码,逻辑上面还有待提高,界面还需要进一步地优化。

    C语言实现代码

    #include"stdio.h"
    #include<stdlib.h>
    #include<conio.h>
    #define getpch(type) (type*)malloc(sizeof(type))
    #define NULL 0
    
    struct pcb //定义进程控制块pcb
    {
    	char name[10];
        char state;
    	int super;
    	int ntime;
    	int rtime;
    	struct pcb *link;
    }*ready=NULL,*p;
    
    typedef struct pcb PCB;
    sort()//建立对进程进行优先级排列函数
    {
    	PCB *first ,*second;
    	int insert=0;
    	if((ready==NULL)||((p->super)>(ready->super)))//优先级最大者,插入队首
    	{
    		p->link=ready;
    		ready=p;}
    	else
    	{
    		first=ready;
    		second=first->link;
    		while(second!=NULL)
    		{
    			if((p->super)>(second->super))//若插入进程比当前进程优先级大
    			{/*插入到当前进程前面*/
    				p->link=second;
    				first->link=p;
    				second=NULL;
    				insert=1;}
    			else //插入进程优先级最低,则插入到队尾
    			{
    				first=first->link;
    				second=second->link;}
    		}//while结束
    		if(insert==0)
    			first->link=p;
    	}
    }
    
    input() //建立进程控制块函数
    {
    	int i,num;
    //	clrscr();//清屏
    	printf("\n 请输入进程号个数?");
    	scanf("%d",&num);
    	for(i=0;i<num;i++)
    	{
    		printf("\n 进程号No.%d:\n",i);
    		p=getpch(PCB);
    		printf("\n 输入进程名:");
    		scanf("%s",p->name);
    		printf("\n 输入进程优先数:");
    		scanf("%d",&p->super);
    		printf("\n 输入进程运行时间:");
    		scanf("%d",&p->ntime);
    		printf("\n");
    		p->rtime=0;
    		p->state='w';
    		p->link=NULL;
    		sort(); //调用sort函数
    	}
    }
    
    int space()
    {
    	int l=0;
    	PCB *pr=ready;
    	while(pr!=NULL)
    	{
    		l++;
    		pr=pr->link;
    	}
    	return(l);
    }
    
    disp(PCB *pr) //建立进程显示函数,用于显示当前进程
    {
    	printf("\n qname \t state \t super \t ndtime \t runtime \n");
    	printf("|%s\t",pr->name);
    	printf("|%c\t",pr->state);
    	printf("|%d\t",pr->super);
    	printf("|%d\t",pr->ntime);
    	printf("|%d\t",pr->rtime);
    	printf("\n");
    }
    
    check() //建立进程查看函数
    {
    	PCB *pr;
    	printf("\n ****当前正在运行的进程是:%s",p->name); //显示当前运行的进程
    	disp(p);
    	pr=ready;
    	printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列的状态
    	while(pr!=NULL)
    	{
    		disp(pr);
    		pr=pr->link;
    
    	}
    }
    
    destroy() //建立进程撤销函数
    {
    	printf("\n 进程[%s] 已完成.\n",p->name);
    	free(p);
    }
    
    running() //建立进程就绪函数
    {
    	(p->rtime)++;
    	if(p->rtime==p->ntime)
    		destroy(); //调用destroy函数
    	else
    	{
    		(p->super)--;
    		p->state='w';
    		sort();  
    	}
    }
    
    main()
    {
    	int len,h=0;
    	char ch;
    	input();
    	len=space();
    	while((len!=0)&&(ready!=NULL))
    	{
    		ch=getchar();
    		h++;
    		printf("\n The execute number:%d \n",h);
    		p=ready;
    		ready=p->link;
    		p->link=NULL;
    		p->state='R';
    		check();
    		running();
    		printf("\n 按任一键继续……");
    		ch=getchar();
    	}
    	printf("\n\n 进程已经完成. \n");
    	ch=getchar();
    	return 0;
    }
    

    存储管理

    目的和要求

    目的
    1:通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉虚存管理的各种页面淘汰算法。
    2:通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。
    要求
    设计一个固定式分区分配的存储管理方案,并模拟实现分区的分配和回收过程。可以假定每个作业都是批处理作业,并且不允许动态申请内存。为实现分区的分配和回收,可以设定一个分区说明表,按照表中的有关信息进行分配,并根据分区的分配和回收情况修改表。

    内容与步骤

    假定每个作业都是批处理作业,并且不允许动态申请内存。为实现分区的分配和回收,设定一个分区说明表,按照表中的有关信息进行分配,并根据分区的分配和回收情况修改该表。

    HTML代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            h1{
                position: absolute;
                right: 288px;
                top: 81px;
                width: 10px;
                font-size: 44px;
            }
            p{
                color:purple;
                font-family: STXingkai;
            }
            span{
                margin-left: 35px;
                margin-top: 100px;
            }
            #showcontent span{
                margin-right: 35px;
            }
            #alocatebox,#showbox,#recylebox{
                padding: 50px;
                border: 1px;
                width: 600px;
                margin: 40px;
            }
    
            .im-com{
                /*width:800px;*/
                height:850px;
                background:url(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1558862265029&di=844ed2dec44eb9014a3450e13e3bbb7c&imgtype=0&src=http%3A%2F%2Fs10.sinaimg.cn%2Fmiddle%2F00378002g7a90910f4dc9%26690) no-repeat top left scroll;
                background-size:cover;
                background-position-y: -20px;
            //margin:40px;
            }
            .hid{
                display: none;
            }
            input{
                text-align: center;
                -webkit-border-radius: 10px;
                -moz-border-radius: 10px;
                border-radius: 10px;
            }
        </style>
    </head>
    <body>
    <h1 align="center"><font color="#87ceeb">存储管理</font></h1>
    <div class="im-com">
        <div id="showbox" style="text-align:center; vertical-align:middle;">
            <p>分区</p>
            <p>
                <span>编号</span><span>大小</span><span>状态</span><span>运行进程ID</span>
            </p>
            <p id="showcontent">
    
            </p>
        </div>
    
        <div id="alocatebox" style="text-align:center; vertical-align:middle;">
            <big>
            <p>请输入作业号</p>
            <input type="text" title="sdf" id="num">
            <p>请输入作业内存大小</p>
            <input type="text" title="sd" id="size"><br/>
            <button type="button" id="sure1" style="margin-top: 20px; border-radius: 10px; background: pink">sure</button>
            </big>
            <button id="start_recycle" type="button" title="sdf" style="display: block;margin-left: 265px; margin-top: 40px;border-radius: 10px; background: skyblue ">
                开始回收
            </button>
        </div>
    
        <div id="recyclebox" class="hid" style="margin-left:277px; margin-top:121px; vertical-align:middle;">
            <big>
            <p>请输入要释放的进程号</p>
            <input type="text"  title="dsf" id="rec_num">
            <button type="button" id="sure2">sure</button>
            </big>
        </div>
    </div>
    
    
    <script type="text/javascript" src="cunchu.js"></script>
    </body>
    </html>
    

    JS代码

    /*初始化*/
    let cont = document.getElementById("showcontent");//展示的p盒子
    let freeareas = [];//分区列表
    for (let i = 1; i < 6; i++) {
        let area = {
            id: i,
            size: 100,
            state: "可分配",
            processid: 0
        }//固定分区,大小100,状态可分配,进程id为0表示没有进程
        freeareas.push(area);
    }
    function show() {
        cont.innerHTML = "";
        let t = "空闲";
    
        let con="";
        for (let i = 0; i < freeareas.length; i++) {
            t = freeareas[i].processid===0?"空闲":freeareas[i].processid;
            con = `
            <span>`+freeareas[i].id+`</span><span>`+freeareas[i].size+`</span><span>`+freeareas[i].state+`</span><span>`+t+`</span><br />
            `;
            console.log(con);
            cont.innerHTML += con;
        }
    
    }
    show();
    //  结束初始化
    
    
    
    
    //确定新建进程号并分配分区
    //获取进程信息
    let proid = document.getElementById("num"),
        size = document.getElementById("size");
    //完成获取进程信息
    //获取按钮
    let sure1 = document.getElementById("sure1");
    //完成获取按钮并绑定事件
    sure1.onclick = function () {
        //顺序检查分区是否够用
        let sccess = false;
        for (let i=0;i<freeareas.length;i++){
            if (freeareas[i].state==="可分配"){
                if (freeareas[i].size >= size.value) {
                    freeareas[i].state = "已分配";
                    freeareas[i].processid = proid.value;
                    sccess = true;
                    break;
                }
                else {
                    break;
                }
            }
        }
        if (!sccess) {
            alert("分配失败");
        }
        show();
    };
    
    //此功能完成
    
    
    //回收内存
    let recybtn = document.getElementById("sure2");
    let recyid = document.getElementById("rec_num");
    
    recybtn.onclick = function () {
        if (recyid.value===""){
            alert("请输入回收进程的id");
        }else {
            let success = false;
            for (let i = 0; i < freeareas.length; i++) {
                if (freeareas[i].processid === recyid.value) {
                    success = true;
                    freeareas[i].state = "可分配";
                    freeareas[i].processid = 0;
                }
            }
            if (!success){
                alert("没有该进程");
            }
        }
        show();
    };
    let alocatebox = document.getElementById("alocatebox"),
        recycle_box = document.getElementById("recyclebox"),
        start_recycle = document.getElementById("start_recycle");
    
    console.log(alocatebox);
    start_recycle.onclick = function () {
        alocatebox.className = "hid";
        recycle_box.className = "";
    };
    

    运行结果

    在这里插入图片描述
    在这里插入图片描述

    问题及心得

    通过此次实验,了解了存储管理相关的知识,掌握了虚存管理的不同页面淘汰算法,同时加强对地址转换过程的了解,此次实验是设计一个固定式分区分配的存储管理方案,模拟实现分区的分配和回收过程,掌握了分区分配的基本原理与流程,并用web将结果显示出来,js的代码还需要进一步的优化,显示的布局与逻辑还需要进一步地改善。

    C语言实现代码

    #include<stdio.h>
    #include<dos.h>
    #include<stdlib.h>
    #include<conio.h>
    #include<iostream.h>
    
    #define n 10 //假定系统允许的最大作业数为n,假定模拟实验中n的值为10
    #define m 10 //假定系统允许的空闲区表最大为m,假定模拟实验中m的值为10
    #define minisize 100 //空闲分区被分配时,如果分配后剩余空间小于minisize,则将该空闲分区全部分配,若大于minisize,则切割分配
    
    struct
    {
    	float address;//已分配分区起始地址
    	float length;//已分配分区长度,单位为字节
    	int flag;//已分配区表登记栏标志,用0表示空栏目
    }used_table[n];//已分配区表
    
    struct
    {
    	float address;//空闲区起始地址
    	float length;//空闲区长度,单位为字节
    	int flag;//空闲区表登记栏标志,用0表示空栏目,用1表示未分配
    }free_table[m];//空闲区表
    
    void allocate(char J,float xk)//给J作业,采用最佳分配算法分配xk大小的空间
    {
    	int i,k;
    	float ad;
    	k=-1;
    	for(i=0;i<m;i++) //寻找空间大于xk的最小空闲区登记项k
    		if(free_table[i].length>=xk && free_table[i].flag==1)
    			if(k==-1 ||free_table[i].length<free_table[k].length)
    				k=i;
    			if(k==-1)
    			{
    				printf("无可用空闲区\n");
    				return;
    			}
    			//找到可用空闲区,开始分配:若空闲区大小与要求分配的空间差小于minisize大小,则空闲区全部分配
    			//若空闲区大小与要求分配的空间差大于minisize,则从空间区划出一部分分配
    			if(free_table[k].length-xk<=minisize)
    			{
    				free_table[k].flag=0;
    				ad=free_table[k].address;
    				xk=free_table[k].length;
    			}
    			else
    			{
    				free_table[k].length=free_table[k].length-xk;
    				ad=free_table[k].address+free_table[k].length;
    			}
    			//修改已分配区表
    			i=0;
    			while(used_table[i].flag!=0 && i<n) //寻找空表目
    				i++;
    			if(i>=n) //无表目可填写已分配分区
    			{
    				printf("无表目填写已分分区,错误\n");
    				//修正空闲区表
    				if(free_table[k].flag==0)
    					//前面找的是整个空闲分区
    					free_table[k].flag=1;
    				else
    				{ //前面找到的是某个空闲分区的一部分
    					free_table[k].length=free_table[k].length+xk;
    					return;
    				}
    			}
    			else
    			{//修改已分配表
    				used_table[i].address=ad;
    				used_table[i].length=xk;
    				used_table[i].flag=J;
    			}
    			return;
    }//主存分配函数结束
    
    void reclaim(char J)//回收作业名为J的作业所占主存空间
    {
    	int i,k,j,s,t;
    	float S,L;
    	//寻找已分配表中对应登记项
    	s=0;
    	while((used_table[s].flag!=J || used_table[s].flag==0) && s<n)
    		s++;
    	if(s>=n) //在已分配表中找不到名字为J的作业
    	{
    		printf("找不到该作业\n");
    		return;
    	}
    	//修改已分配表
    	used_table[s].flag=0;
    	//取得归还分区的起始地址S和长度L
    	S=used_table[s].address;
    	L=used_table[s].length;
    	j=-1;
    	k=-1;
    	i=0;
    	//寻找回收分区的空闲上下邻,上邻表目k,下邻表目j
    	while(i<m && (j==-1 || k==-1))
    	{
    		if(free_table[i].flag==1)
    		{
    			if(free_table[i].address+free_table[i].length==S)
    				k=i;//找到上邻
    			if(free_table[i].address==S+L)
    				j=i;//找到下邻
    		}
    		i++;
    	}
    	if(k!=-1)
    		if(j!=-1)//上邻空闲区,下邻空闲区,三项合并
    		{
    			free_table[k].length=free_table[j].length+free_table[k].length+L;
    			free_table[j].flag=0;
    		}
    		else//上邻空闲区,下邻非空闲区,与上邻合并
    			free_table[k].length=free_table[k].length+L;
    		else
    			if(j!=-1)
    				//上邻非空闲区,下邻为空闲区,与下邻合并
    			{
    				free_table[j].address=S;
    				free_table[j].length=free_table[j].length+L;
    			}
    			else
    				//上下邻均为非空闲区,回收区域直接填入
    			{
    				//在空闲区表中寻找空栏目
    				t=0;
    				while(free_table[t].flag==1 && t<m)
    					t++;
    				if(t>=m)//空闲区表满,回收空间失败,将已分配表复原
    				{
    					printf("主存空闲表没有空间,回收空间失败\n");
    					used_table[s].flag=J;
    					return;
    				}
    				free_table[t].address=S;
    				free_table[t].length=L;
    				free_table[t].flag=1;
    			}
    			return;
    }//主存回收函数结束
    
    int main()
    {
    	int i,a;
    	float xk;
    	char J;
    	//空闲分区表初始化
    	free_table[0].address=10240;//起始地址假定为10240
    	free_table[0].length=10240;//长度假定为10240,即10k
    	free_table[0].flag=1;//初始空闲区为一个整体空闲区
    
    	for(i=1;i<n;i++)
    		free_table[i].flag=0;//其余空闲分区表项未被使用
    	//已分配表初始化
    	for(i=0;i<n;i++)
    		used_table[i].flag=0;//初始时均未分配
    	while(1)
    	{
    		printf("选择功能项(0-退出,1-分配主存,2-回收主存,3-显示主存\n");
    		printf("选择功能项(0-3):");
    		scanf("%d",&a);
    		switch(a)
    		{
    		case 0:exit(0);//a=0程序结束
    		case 1://a=1分配主存空间
    			printf("输入作业名 J 和作业所需长度 xk :");
    			scanf("%*c%c%f",&J,&xk);
    			allocate(J,xk);
    			break;
    		case 2://a=0回收主存空间
    			printf("输入要回收分区的作业名");
    			scanf("%*c%c",&J);
    			reclaim(J);//回收主存空间
    			break;
    		case 3://a=3显示主存情况
    			//输出空闲区表和已分配表的内容
    			printf("输出空闲区表:\n 起始地址 分区长度 标志\n");
    			for(i=0;i<m;i++)
    				printf("%6.0f%9.0f%6d\n",free_table[i].address,free_table[i].length,free_table[i].flag);
    			printf("按任意键,输出已分配区表\n");
    			getch();
    			printf("输出已分配区表:\n 起始地址 分区长度 标志\n");
    			for(i=0;i<n;i++)
    				if(used_table[i].flag!=0)
    					printf("%6.0f%9.0f%6c\n",used_table[i].address,used_table[i].length,used_table[i].flag);
    				else
    					printf("%6.0f%9.0f%6d\n",used_table[i].address,used_table[i].length,used_table[i].flag);
    			break;
    		default:printf("没有该选项\n");
    		}
    	}
    	return 1;
    }
    

    动态分区分配

    #include<iostream>
    using namespace std;
    const int Max_length=640;//最大内存
    int a,b;//记录算法编号,b记录操作编号
    struct freearea//空闲区的结构体
    {
    	int ID;//分区号
    	int size;//分区大小
    	int address;//分区地址
    	bool flag;//使用状态,0未占用,1为已占用
    };
    
    typedef struct DuNode//双向链表结点
    {
    	freearea data;//数据域
    	DuNode *prior;//指针域
    	DuNode *next;
    }*DuLinkList;
    DuLinkList m_rid=new DuNode,m_last=new DuNode;//双向链表收尾指针
    
    void init()//空闲区队列初始化
    {
    	m_rid->prior=NULL;
    	m_rid->next=m_last;
    	m_last->prior=m_rid;
    	m_last->next=NULL;
    	m_rid->data.size=0;
    	m_last->data.address=0;
    	m_last->data.size=Max_length;
    	m_last->data.ID=0;
    	m_last->data.flag=0;//!!!
    }
    
    void show()
    {
    	DuNode *p=m_rid->next;//指向空闲区队列的首地址
    	cout<<"+++++++++++++++++++++++++++++++++++++"<<endl;
    	while(p)
    	{
    		cout<<"分区号:  ";
    		if(p->data.ID==0)
    			cout<<"FREE"<<endl;
    		else
    			cout<<p->data.ID<<endl;
    		cout<<"分区起始地址:  "<<p->data.address<<endl;
    		cout<<"分区大小:  "<<p->data.size<<endl;
    		cout<<"分区状态:  ";
    		if(p->data.flag)
    			cout<<"已被占用"<<endl;
    		else
    			cout<<"空闲"<<endl;
    		cout<<"-------------------------------------"<<endl;
    		p=p->next;
    	}
    }
    
    bool first_fit(int id,int m_size)//首次适应算法
    {
    	DuNode *p=m_rid->next;//指向空闲区队列的首地址
    	DuLinkList fa=new DuNode;//新建一个空闲区并赋值
    	//memset(fa,0,sizeof(DuNode));
    	fa->data.ID=id;
    	fa->data.size=m_size;
    	fa->data.flag=1;//表示被占用
    	while(p)//在空闲区列表中从低地址向高地址查找
    	{
    		if(p->data.size>=m_size && !p->data.flag)//找到大于等于所需的内存的空闲区
    		{
    			if(p->data.size==m_size)//刚好空闲区大小与所需大小相等
    			{
    				p->data.ID=id;
    				p->data.flag=1;
    				free(fa);//清空新创建的空闲区
    				return true;
    			}
    			else if(p->data.size>m_size)//空闲区比所需内存大,则需要将多的内存放到回收处
    			{
    				fa->data.address=p->data.address;//将空闲区的前半部分分出去
    				p->data.address+=m_size;
    				p->data.size-=m_size;
    				p->prior->next=fa;
    				fa->next=p;
    				fa->prior=p->prior;
    				p->prior=fa;
    				return true;
    			}
    		}
    		p=p->next;
    	}
    	free(fa);//查找分配失败
    	return false;
    }
    
    bool best_fit(int id,int m_size)//最佳适应算法,其中需要查找最佳的存放位置
    {
    	DuNode *p=m_rid->next;//指向空闲区队列的首地址
    	DuNode *q=NULL;//存放最佳地址
    	DuLinkList fa=new DuNode;//新建一个空闲区并赋值
    	memset(fa,0,sizeof(DuNode));
    	fa->data.ID=id;
    	fa->data.size=m_size;
    	fa->data.flag=1;//表示被占用
    	int d=Max_length;//所需内存大小与空闲区大小之间的差值
    	while(p)
    	{
    		if(p->data.size>=m_size && !p->data.flag)//找到大于等于所需的内存的空闲区
    		{
    			if(p->data.size-m_size<d)
    			{
    				q=p;
    				d=q->data.size-m_size;
    			}
    		}
    		p=p->next;
    	}
    	if(q==NULL)//查找分配失败
    		return false;
    	else
    	{
    		if(d==0)//刚好找到与所需内存大小一样的空闲区
    		{
    			p->data.ID=id;
    			p->data.flag=1;
    			free(fa);//清空新创建的空闲区
    			return true;
    		}
    		else//空闲区比所需内存大,则需要将多的内存作为回收处理
    		{
    			fa->data.address=q->data.address;//将空闲区的前半部分分出去
    			q->data.address+=m_size;
    			q->data.size-=m_size;
    			q->prior->next=fa;
    			fa->next=q;
    			q->prior=fa;
    			fa->prior=q->prior;
    			return true;
    		}
    	}
    }
    
    bool allocation()//分配资源
    {
    	int id,m_size;//输入的作业号和内存块大小
    	cout<<"请输入作业编号(分区号)和申请的内存大小(KB):";
    	cin>>id>>m_size;
    	if(m_size<=0)//申请的内存大小小于等于0,申请失败
    	{
    		cout<<"申请的内存大小错误!请重新输入"<<endl;
    		return false;
    	}
    	if(a=1)//首次适应算法
    	{
    		if(first_fit(id,m_size))
    		{
    			cout<<"内存分配成功!"<<endl;
    			show();//显示内存分布
    		}
    		else
    			cout<<"内存不足,分配失败!"<<endl;
    		return true;
    	}
    	if(a=2)//最佳适应算法
    	{
    		if(best_fit(id,m_size))
    		{
    			cout<<"内存分配成功!"<<endl;
    			show();//显示内存分布
    		}
    		else
    			cout<<"内存不足,分配失败!"<<endl;
    		return true;
    	}
    }
    
    void recycle()//回收内存
    {
    	int id;
    	cout<<"请输入想要释放的作业号:";
    	cin>>id;
    	DuNode *p=m_rid->next;//指向空闲队列的首地址
    	DuNode *p1=NULL;//辅助向量
    	while(p)//查找需要释放的作业的地址进行合并工作
    	{
    		if(p->data.ID==id)
    		{
    			p->data.ID=0;
    			p->data.flag=0;
    			if(!p->prior->data.flag)//与前一个空闲区相邻,则合并
    			{
    				p->prior->data.size+=p->data.size;
    				p->prior->next=p->next;
    				p->next->prior=p->next;
    			}
    			if(!p->next->data.flag)//与后一个空闲区相邻,则合并
    			{
    				p->data.size+=p->next->data.size;
    				p->next->next->prior=p;
    				p->next=p->next->next;
    			}
    			break;
    		}
    		p=p->next;
    	}
    	show();
    }
    
    
    void main()
    {
    	cout<<"*****************动态分区分配模拟*********************"<<endl;
    	cout<<"************1.首次适应算法  2.最佳适应算法************"<<endl;
    	cout<<"请输入要选择的分配算法:";
    	cin>>a;
    	init();//初始化内存块
    	while(a!=1 && a!=2)
    	{
    		cout<<"输入错误!请重新输入:"<<endl;
    		cin>>a;
    	}
    	while(1)
    	{
    		cout<<"**************************************************"<<endl;
    		cout<<"*********1.申请内存 2.释放内存 3.退出*************"<<endl;
    		cout<<"请输入操作数:";
    		cin>>b;
    		switch(b)
    		{
    		case 1:
    			allocation();
    			break;
    		case 2:
    			recycle();
    			break;
    		case 3:
    		default:
    				cout<<"动态分区分配算法结束!"<<endl;
    				exit(1);
    				break;
    		}
    	}
    }
    

    死锁避免银行家算法

    目的和要求

    目的
    系统中有限的资源要供多个进程使用,保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。
    要求
    每个进程的资源需求总量不能超过系统拥有的资源总数, 利用银行算法进行资源分配可以避免死锁。

    内容与步骤

    程序流程图
    初始化算法流程图
    在这里插入图片描述
    银行家算法流程图
    在这里插入图片描述
    安全性算法流程图
    在这里插入图片描述

    运行结果

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    问题及心得

    通过此次实验,解决了银行家死锁问题,通过初始化函数,调用银行家算法,进行安全算法的检查,最终正确合理地分配了资源,成功地避免了死锁问题,得出了相关的安全序列。此次的界面通过web显示出来,js脚本语言还需要进一步地加强,出现了一点逻辑问题,并且安全序列也没有很好地解决,存在一些冲突性事件。

    C语言实现关键代码

    安全性算法

    //安全性算法
    bool SafeAlgorithm()
    {
    	int i,j;
    	//初始化Finish向量
    	for(i=0;i<n;++i)
    	{
    		Finish[i]=false;
    	}
    	//初始化工作向量
    	for(j=0;j<m;++j)
    	{
    		Work[j]=Available[j];
    	}
    
    	int iProcNum;
    	//选择满足条件的进程
    	i=0;
    	while(SelectProcess(iProcNum))
    	{
    		Finish[iProcNum]=true;
    		PrintSafeSeries(iProcNum);//输出此时利用安全性算法的分析情况
    		int k;
    		for(k=0;k<m;++k)
    		{
    			Work[k]+=Allocation[iProcNum][k];
    		}
    		SafeSeries[i++]=iProcNum;//进程号加入安全序列数组
    	}
    
    	if(IsSafe())
    	{
    		return true;//存在一个安全序列
    	}
    	return false;//不存在一个安全序列
    }
    

    银行家算法

    //银行家算法
    void BankAlgorithm()
    {
    	int i,j;
    	cout<<"请输入请求分配的进程号(0-"<<n-1<<"):";
    	cin>>i;
    	cout<<"请依次输入进程P"<<i<<"对"<<m<<"类资源的请求分配量:";
    	for(j=0;j<m;++j)
    	{
    		cin>>Request[i][j];
    	}
    
    	//步骤一
    	for(j=0;j<m;++j)
    	{
    		if(Request[i][j]>Need[i][j])
    		{
    			cout<<"请求的资源已超过该资源宣布的最大值,请求资源失败!!"<<endl;
    			return;
    		}
    	}
    
    	//步骤二
    	for(j=0;j<m;++j)
    	{
    		if(Request[i][j]>Available[j])
    		{
    			cout<<"没有足够的资源,请求资源失败!!"<<endl;
    			return;
    		}
    	}
    
    	//步骤三
    	//系统试探着把资源分配给进程Pi,并修改相应的数值
    	for(j=0;j<m;++j)
    	{
    		Available[j]-=Request[i][j];
    		Allocation[i][j]+=Request[i][j];
    		Need[i][j]-=Request[i][j];
    	}
    
    	//步骤四
    	//系统执行安全性算法
    	if(!SafeAlgorithm())//检测到不安全,则恢复到原来的状态
    	{
    		for(j=0;j<m;++j)
    		{
    			Available[j]+=Request[i][j];
    			Allocation[i][j]-=Request[i][j];
    			Need[i][j]+=Request[i][j];
    		}
    	}
    }
    

    在这里插入图片描述

    展开全文
  • 针对J2ME程序数据持久存储的问题,根据移动信息设备简表,提出一种采用缓存机制的面向对象的数据持久存储管理方案。该方案将数据封装为对象,在应用程序和持久存储之间采用数据管理层分离应用程序的数据访问逻辑和...
  • 因此企业管理员联系到存储工程师,询问是否有办法将误删除的数据恢复,同时,管理员又 提到,如果为了数据的安全性每天保存数据,那么由于数据量过大,数据的完整备份非常慢, 如何解决这个问题。 【需求分析】 需求...
  • Linux进程存储管理

    2017-07-04 15:14:19
    程序代码test.c+运行结果实验分析: 代码区(test):指令常量、const声明变量、字符串常量。 数据段(data):全局或静态已经初始化的变量。 未初始化的数据段(bss):没有初始化的全局
  • 二、 实验内容(实验过程、代码和结果截图) 1. 创建简单存储过程 创建一个名为stu_pr的存储过程,该存储过程能查询出051班学生的所有资料,包括学生的基本信息、学生的选课信息(含未选课同学的信息)。要求在创建...
  • (逐题给出相应的SQL语句及执行结果,SQL语句必须能够拷贝,实验结果可截图;题目内容不需抄写) 在之前的实验基础上继续完成,之前实验已经建立有相关的jxgl数据库。 在教学管理系统(jxgl)中完成以下操作: 查看并...
  • 用java实现的存储管理,用Eclipse编写,导入以后绝对能运行,结果正确。还附上上了实验知道书。
  • django应用程序可管理,运行它们并缓存结果。 地位 这是高度实验性的,尚未完成的工作。 如果您正在寻找可以使用的东西,他们会稍后再试... 我之所以公开发布软件包和文档是因为这是我的持续集成系统的一部分。 ...
  • 实验的目的是通过请求页式管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。因为源码中我对一些关键步骤的注释已经比较清晰了,所以在本文中不会再对每一个细节都进行...
  • 1、在该实验中,采用可变分区方式完成对存储空间的管理(即存储空间的分配与回收工作)。 2、设计用来记录主存使用情况的数据结构:已分区表和空闲分区表或链表。 3、在设计好的数据结构上设计一个主存分配算法...
  • 真正的模拟操作系统中 内存的分配 (分页存储管理)(操作系统模拟多进程内存分配) 连续的分配方式会形成许多碎片,虽然通过紧凑的方法将血多碎片拼接成可用的大块空间 但须付出很大的开销。如果允许将一个进程...
  • 采用多道程序设计思想设计一个程序,模拟页式存储管理地址变换的过程,可采用FIFO、LRU、LFU、OPT四种页面置换算法。使用的相关的开发软件为NetBeans IDE 8.2。 解决的主要问题: (1)需要建立访问页表线程、访问快...
  • 真正的模拟操作系统中 内存的分配 (分页存储管理)(操作系统模拟多进程内存分配) 连续的分配方式会形成许多碎片,虽然通过紧凑的方法将血多碎片拼接成可用的大块空间 但须付出很大的开销。如果允许将一个进程...
  • 操作系统原理 实验名称 虚拟页式管理 姓 名 学号 专业班级 实验日期 成 绩 指导教师 实验目的实验原理主要仪器设备实验内容与步骤实验数据记录与处理实验 结果与分析问题建议 实验二 模拟请求页式存储管理中硬件的...
  • 包括实验题目,代码及运行结果 实验8 文件管理(2学时) 一、实验目的 理解文件系统的主要概念及文件系统内部功能和实现过程。 二、实验内容 采用二级文件目录结构,编写程序实现文件系统的文件存储空间的管理...
  • 北京邮电大学远程教育 信息管理与信息系统专业数据...序存储结构和链接存储结构上的运算 二 实验要求 1 认真阅读和掌握本实验的程序 2 上机运行本程序 3 保存和打印出程序的运行结果并结合程序进行分析 4 按照你对线
  • 针对特殊场景下需通过北斗短报文传输大量数据信息的需求,探讨并设计了一种适合于北斗通信的长报文...实验结果表明,该传输协议可实现对长报文丢包的差错重传功能,有效控制“盲目发送”现象,使得有效信息率得到提高。
  • 题 目: 模拟设计段式存储管理中地址转换 初始条件: 1.预备内容:阅读操作系统的内存管理章节内容,理解段式存储管理的思想及相应的分配主存的过程。 2.实践准备:掌握一种计算机高级语言的使用。 要求完成的...
  • 随着物联网、无线传感器网络等技术在煤矿应急管理信息化建设中的广泛应用,煤矿大量监测、控制及自动化等实时系统产生的流式...实验结果表明,基于Hadoop构建的煤矿应急云平台在海量数据存储与处理时均有良好的性能表现。
  • Apache Spark是专为大规模数据处理而设计的快速通用的计算引擎同,它最初是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行框架。 Spark拥有Hadoop MapReduce所具有的...
  • 我们的实验结果支持真实世界和人工备份数据集表明,DARE 完全消耗了标准超级特征方法所需的计算和分类开销的 1/4 和 1/2,而检测则增加了 2-10% 的额外冗余并实现了成功输出,通过利用现有的重复接近度知识进行相似...
  • logkv 事件日志处理和分析在安全管理,IT故障排除以及用户行为分析等应用程序中发挥着关键作用。 近年来,系统规模Swift增长,日志事件数据量也相应快速... 初步实验结果表明,LogKV是一种很有前途的解决方案。 请参

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 404
精华内容 161
关键字:

存储管理实验结果