操作系统实现及其可视化实现(Java语言)

本文将介绍操作系统常见的几种算法并给出实现方法,系统架构图如下:

如需源码请参见文章末尾链接

进程管理

        1.生产者消费者与读者写者

            生产者消费者问题其主要实现就是模拟进程之间的同步与互斥,首先需要设置3个令牌(信号量),即:Empty、Full、mutex(互斥)。

             生产者首先需判断获取空的缓冲池,判断是否有空间生产(Empty.acquire());有空间后紧接着就是获取互斥信号量mutex,当获取到mutex就能对临界区进行修改,完成相应的生产任务,记录型信号量增加(即生产,count++)。在随即等待一段时间后(现代计算机CUP处理速度较快,wait是为了能使我们能够看清流程)退出剩余区,即mutex.release()。最后增加一个Full空间(Full..release())。

           消费者与之类似,其不同点仅在于其进入临界区消费与退出时的判断逻辑为:是否有空间(产品)消费和增加一个Empty空间(Empty.release())。

           常见的进程调度在java中一般使用令牌+进程锁+LinkedList实现基本同步互斥问题,生产者消费者实现核心代码如下:

try
{
    synchronized(this){
        Random random = new Random();
        wait(random.nextInt(500));
        ProderAndConsumer.insert3("生产者"+num+"打算生产");
        ProderAndConsumer.Pro.add(num+"打算生产");
        ProderAndConsumer.Empty.acquire();
        ProderAndConsumer.mutex.acquire();
        ProderAndConsumer.insert2("生产者"+num+"正在生产");
        ProderAndConsumer.Pro.remove(num+"打算生产");
        ProderAndConsumer.ing.add("生产者"+num+"正在生产");
        wait(random.nextInt(10000)+3000);
        ProderAndConsumer.count++;
        ProderAndConsumer.insert2("生产者"+num+"结束生产");
        ProderAndConsumer.insert3("生产者"+num+"完成生产");
        ProderAndConsumer.ing.remove("生产者"+num+"正在生产");
        wait(3000);
        ProderAndConsumer.fresh.acquire();
        ProderAndConsumer.refresh();//刷新页面,通过队列的信息刷新页面
        ProderAndConsumer.fresh.release();
        ProderAndConsumer.mutex.release();
        ProderAndConsumer.Full.release();
    }
} catch (InterruptedException e) {
    System.out.println("生产者"+num+"出现错误!");
    e.printStackTrace();
}

try {
    synchronized(this) {
        Random random = new Random();
        wait(random.nextInt(400));
        ProderAndConsumer.insert1("消费者"+num+"打算消费");
        ProderAndConsumer.Con.add(num+"打算消费");
        ProderAndConsumer.Full.acquire();
        ProderAndConsumer.mutex.acquire();
        ProderAndConsumer.insert2("消费者"+num+"正在消费");
        ProderAndConsumer.Con.remove(num+"打算消费");
        ProderAndConsumer.ing.add("消费者"+num+"正在消费");
        wait(random.nextInt(5000)+1500);
        ProderAndConsumer.count--;
        ProderAndConsumer.insert2("消费者"+num+"结束消费");
        ProderAndConsumer.ing.remove("消费者"+num+"正在消费");
        ProderAndConsumer.insert1("消费者"+num+"完成消费");
        wait(3000);
        ProderAndConsumer.fresh.acquire();              //实现刷新页面时,线程的互斥
        ProderAndConsumer.refresh();                    //刷新页面,通过队列的信息刷新页面
        ProderAndConsumer.fresh.release();
        ProderAndConsumer.mutex.release();
        ProderAndConsumer.Empty.release();
    }

} catch (InterruptedException e) {
    System.out.println("消费者"+num+"出现错误!");
    e.printStackTrace();
}

            读者写者问题是在生产者消费者问题的基础上改进而来,其不同点仅在于加入一个计数变量count来记录处于读写空间中读者的数量,实现读者可同时读文件,其核心代码如下:

try {
            synchronized(this)
            {
                Random random = new Random();
                wait(random.nextInt(500));
                ReadAndWrite.insert1("读者"+num+"打算读文件");

                ReadAndWrite.Re.add(num+"打算读文件");

                ReadAndWrite.w.acquire();           //实现写优先
                ReadAndWrite.mutex.acquire();       //防止读者之间同步访问count,读者互斥访问count
                if(ReadAndWrite.count==0)
                    ReadAndWrite.rw.acquire();      //实现读写互斥
                ReadAndWrite.count++;               //我只要有东西正在读你,你就不许给我写东西,实现多读者同步的关键
                ReadAndWrite.mutex.release();
                ReadAndWrite.w.release();

                //以下为读文件的阶段
                ReadAndWrite.insert2("读者"+num+"正在读文件");
                ReadAndWrite.ing.add("读者"+num+"正在读文件");
                wait(random.nextInt(5000)+1500);
                ReadAndWrite.insert2("读者"+num+"结束读文件");
                ReadAndWrite.insert1("读者"+num+"完成读文件");
                ReadAndWrite.ing.remove("读者"+num+"正在读文件");
                ReadAndWrite.Re.remove(num+"打算读文件");
                //以上为读文件的阶段

                wait(3000);
                ReadAndWrite.fresh.acquire();        //实现刷新页面时,线程的互斥
                ReadAndWrite.refresh();              //刷新页面,通过队列的信息刷新页面
                ReadAndWrite.fresh.release();

                ReadAndWrite.mutex.acquire();
                ReadAndWrite.count--;           //文件读完了,读完一个出来一个,count--了
                if(ReadAndWrite.count==0)
                    ReadAndWrite.rw.release();
                ReadAndWrite.mutex.release();
            }

        } catch (InterruptedException e) {
            System.out.println("读者"+num+"出现错误!");
            e.printStackTrace();
        }



    try {
            synchronized(this) {
                Random random = new Random();
                wait(random.nextInt(500));
                ReadAndWrite.insert3("写者"+num+"打算写文件");
                ReadAndWrite.Wr.add(num+"打算写文件");
                ReadAndWrite.w.acquire();
                ReadAndWrite.rw.acquire();
                ReadAndWrite.insert2("写者"+num+"正在写文件");
                ReadAndWrite.ing.add("写者"+num+"正在写文件");
                wait(random.nextInt(10000)+3000);
                ReadAndWrite.insert2("写者"+num+"结束写文件");

                ReadAndWrite.insert3("写者"+num+"完成写文件");
                ReadAndWrite.ing.remove("写者"+num+"正在写文件");
                ReadAndWrite.Wr.remove(num+"打算写文件");

                wait(3000);
                ReadAndWrite.fresh.acquire();
                ReadAndWrite.refresh();//刷新页面,通过队列的信息刷新页面
                ReadAndWrite.fresh.release();

                ReadAndWrite.rw.release();
                ReadAndWrite.w.release();
            }
        } catch (InterruptedException e) {
            System.out.println("写者"+num+"出现错误!");
            e.printStackTrace();
        }

         运行界面:

        2.银行家算法

          银行家算法基于安全性算法实现,其目的是避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。

int[][] Allocation = new int[ab][res];
		int[][] Max = new int[ab][res];
		int[][] Need = new int[ab][res];
		int[] Available = new int[res];
		int[] alloc_avail = new int[res];		//可用资源数

        安全性算法:

        设置工作向量Work,有m个元素,表示系统中的剩余可用资源数目。在执行安全性算法开始时,Work=Available。

  1.    初始化安全序列为空。
  2. 从Need矩阵中找到符合下面条件的行:该行对应的进程不在安全序列中,而且该行小于等于Work向量,找到后,把对应的进程加入安全序列;若找不到,则执行步骤4。
  3. 进程Pi进入安全序列后,可顺利执行,直至完成,并释放分配给它的资源,因此应执行Work=Work+Allocation[i],其中Allocation[i]表示进程Pi代表的在Allocation矩阵中对应的行,返回步骤2。
  4. 若此时安全序列中已有所有进程,则系统处于安全状态,否则系统处于不安全状态(不安全状态不意味着一定会发生死锁)。          

        核心代码如下:

while(true) {
			f=0;
			if(ip==ab) ip=0;
			if(unsafe_chk[ip]==1 && tnp<=1) {
				f=1;
				break;
			}
			if(process_complete[ip] == 1) {
				ip++;
				continue;
			} else {
				for(c=0;c<res;c++) {
					if(Available[c]<Need[ip][c]) f=1;
				}
				if(f==1) {
					for(c=0;c<res;c++) {
						if(alloc_avail[c]<Need[ip][c]) unsafe_chk[ip]=1;
					}
					ip++;
					continue;
				} else {
					process_complete[ip]=1;
					System.out.println("进程"+ip+"可以分配资源..");
					System.out.println("进程终止,释放资源..");
					System.out.println("释放后可用的资源有:");
					for(c=0;c<res;c++) {
						Available[c] += Allocation[ip][c];
						System.out.print(Available[c]+" ");
					}
					System.out.println("\n");
					ip++;
					tnp--;
					if(tnp==0) break;
				}
			}
		}
		}
		if(tnp==0) System.out.println("Safe");

实现结果:

 

 

 

实现源码资源链接:实现源码资源链接icon-default.png?t=M4ADhttps://download.csdn.net/download/zxl316616/85656014

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
一、UNIX文件系统的基本原理        UNIX采用树型目录结构,每个目录表称为一个目录文件。一个目录文件是由目录项组成的。每个目录项包含16B,一个辅存磁盘块(512B)包含32个目录项。在目录项中,第1、2字节为相应文件的外存i节点号,是该文件的内部标识;后14B为文件名,是该文件的外部标识。所以,文件目录项记录了文件内、外部标识的对照关系。根据文件名可以找到辅存i节点号,由此便得到该文件的所有者、存取权、文件数据的地址健在等信息。UNIX的存储介质以512B为单位划分为块,从0开始直到最大容量并顺序加以编号就成了一个文件卷,也叫文件系统。本次课程设计是要实现一个简单的模拟UNIX文件系统。我们在磁盘中申请一个二进制文件模拟UNIX内存,依次初始建立位示图区,I节点区,数据块区。 二、基本要点思路         1、模拟磁盘块的实现:因为文件系统需要从磁盘中读取数据操作数据,在实现时是使用文件来模拟磁盘,一个文件是一块磁盘,在文件中以划分磁盘块那样划分不同的区域,主要有三个区域:位图区,inode索引节点区,磁盘块区。位图区我是使用一个512byte的数组存放,inode区和磁盘块区我采用一种自认为比较巧妙的方法,就是存放对象列表,之前说过,在本次实验的所有的结构都使用对象进行存储,而inode节点和磁盘块就是两个重要的数据结构,在初始时我实例32个inode对象和512个block对象(至于这些类的具体定义下面会提到),然后将这些对象加入各自对应的对象列表中,在存储时,使用java的对象序列技术将这个对象数组存到磁盘中。当使用文件系统时,程序会先从磁盘文件中读取出位图数组,inode对象列表,block对象列表,之后的操作就是通过对这些列表进行修改来实现。使用这种方法可以减小存储的空间(对象序列话技术)而且不需要在使用时进行无用的查找,只要第一次初始中将这些对象都读取出来。        2、界面的实现:在实现这个文件系统时使用了两种方案,一种是直接在java控制台来进行输入输出,因为原本想着UNIX文件系统原本也是使用的命令行语句,所以在控制台上实现也很接近。后来在老师的建议下又将整个程序重新修改,改成在UI界面上进行输入输出,这样确实界面美观舒服了不少,只不过两者用的技术很不一样,前者主要使用的是系统的输入输出流,后者使用java监听器。        3、权限的实现:在实现多用户的权限方面,我给文件和文件夹各定义了三级权限1、访问:在文件中是可以查看文件的内容,在文件夹中是可以进入该文件夹。2、修改:文件中是可以对文件进行编辑,文件夹中是可以在该文件夹中创建新的文件或目录。3、删除:顾名思义。文件或文件夹的创建者拥有最高级别的权限,只有拥有最高级权限的用户才可以给其他用户针对该文件或文件夹进行授权和授权操作。在每次对文件或文件夹进行访问修改删除操作时都会检查当前用户在该文件或文件夹所拥有的权限,只有拥有的权限大于想要实现的权限时才可以进行该操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

轻歌吟松风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值