精华内容
下载资源
问答
  • java学生宿舍管理系统,来了就点个赞再走呗,即将毕业的兄弟有福了
    万次阅读 多人点赞
    2021-04-29 16:52:19

    引言:

    上次写了一个学生成绩管理系统,有个老铁说不会运行,我答应给他写一个项目,并且附上运行的文档,于是这几天就利用摸鱼时间、晚上休息时间、中午午休时间写了这个宿舍管理系统,表的设计、代码编写都是自己弄的,数据库用mysql,web容器用 tomcat,开发工具用eclipse\myeclipse,java方面入口都是用servlet,数据库连接用c3p0,总之都是用比较基础的东西来写的,简单易懂,对于正在做毕业设计和刚入门时间不长的兄弟们来说,应该是比较好的学习代码了,希望对大家有所帮助。

    一张界面图:

    角色介绍

    1.超级管理员 

    超级管理员是权限最大的角色,拥有系统所有的权限。

    2.宿舍管理员

    权限:学生管理、宿舍管理、考勤管理、修改密码。

    注意:宿舍管理员所管理的这几个模块,都是超级管理员给他指定权限范围&#x

    更多相关内容
  • 算法采用文件管理学生的信息,同时通过人机交互方式操作系统的执行
  • 操作系统课设 分页式存储管理(内含OPT,FIFO,LRU,LFU四种算法用到了线程),用eclipse打开,我给的是创建的整个源包,打开就可以运行,这个是经过最佳改正过的
  • 充分发挥Md5算法在加解密技术上的应用,根据车主身份证号以及车牌号计算生成Md5值,然后再和保存在文件系统中的Md5值进行比较,进而确定提车人的合法性。
  • 学生信息管理系统

    千次阅读 2017-01-09 21:21:23
    1、学生信息管理系统C语言版:# include # include # include <string.h>struct Student { int age; float score; char name[100];}; void inputdata(Student * arr,int len)//无论是赋值还是输出数

    核心内容:
    1、学生信息管理系统


    C语言版:

    # include <stdio.h>
    # include <malloc.h>
    # include <string.h>
    
    struct Student
    {
        int age;
        float score;
        char name[100];
    
    };
    void inputdata(Student * arr,int len)//无论是赋值还是输出数值
    {
        arr[0].age = 20;
        arr[0].score = 88.8f;
        strcpy(arr[0].name,"zhangsan");
    
        arr[1].age = 21;
        arr[1].score = 98.8f;
        strcpy(arr[1].name,"lisi");
    
        arr[2].age = 18;
        arr[2].score = 66.6f;
        strcpy(arr[2].name,"lidong");
    }
    
    void sort(Student * arr,int len)
    {
        for (int j=1; j<len;j++)
        {
           for (int k=0; k<len-j;k++)
           {
               Student tmp;
               if (arr[k].score > arr[k+1].score)
               {
                   tmp = arr[k];
                   arr[k] = arr[k+1];
                   arr[k+1] = tmp;
               }
           }
        }
    
    }
    void outputdata(Student * arr,int len)
    {
        //接下来我们将结果进行输出
        for (int i=0; i<3; i++)
        {
            printf("%d\t",arr[i].age);
            printf("%f\t",arr[i].score);
            printf("%s\t",arr[i].name);
            printf("\n");
        }
    
    }
    int main(void)
    {
        Student * arr = (Student *)malloc(sizeof(Student)*3);
    
        inputdata(arr,3);
        sort(arr,3);
        outputdata(arr,3);
    
        return 0;
    }

    运行结果:
    这里写图片描述
    Java语言版:

    import java.util.ArrayList;
    import java.util.Collections;
    
    
    
    
    class Student  implements Comparable<Student>
    {
        public int age;
        public float score;
        public String name;
        public Student(int age,float score,String name)
        {
            this.age = age;
            this.score = score;
            this.name = name;
        }
        @Override
        public int compareTo(Student obj)
        {
            if (this.score > obj.score)
                return 1;
            else 
                return -1;
        }
        public String toString()
        {
            return this.age+"\t"+this.score+"\t"+this.name;
        }
    }
    public class App1 
    {
        public static void main(String[] args)
        {
           ArrayList<Student> arr = new ArrayList<Student>();//动态分配一块内存空间,用指针变量指向这块内存空间
           arr.add(new Student(20,88.8f,"zhangsan"));
           arr.add(new Student(21,98.8f,"lisi"));
           arr.add(new Student(18,66.6f,"lidong"));
    
           for (int i=0; i<arr.size();i++)
           {
               System.out.println(arr.get(i));
           }
    
           Collections.sort(arr);
    
           for (int i=0; i<arr.size();i++)
           {
               System.out.println(arr.get(i));
           } 
        }
    }

    运行结果:

    20  88.8    zhangsan
    21  98.8    lisi
    18  66.6    lidong
    18  66.6    lidong
    20  88.8    zhangsan
    21  98.8    lisi
    展开全文
  • 主宰操作系统的经典算法

    万次阅读 多人点赞 2020-07-24 15:22:50
    进程和线程管理中的算法 进程和线程在调度时候出现过很多算法,这些算法的设计背景是当一个计算机是多道程序设计系统时,会频繁的有很多进程或者线程来同时竞争 CPU 时间片。 那么如何选择合适的进程/线程运行是一项...

    此篇文章带你梳理一下操作系统中都出现过哪些算法

    进程和线程管理中的算法

    进程和线程在调度时候出现过很多算法,这些算法的设计背景是当一个计算机是多道程序设计系统时,会频繁的有很多进程或者线程来同时竞争 CPU 时间片。 那么如何选择合适的进程/线程运行是一项艺术。当两个或两个以上的进程/线程处于就绪状态时,就会发生这种情况。如果只有一个 CPU 可用,那么必须选择接下来哪个进程/线程可以运行。操作系统中有一个叫做 调度程序(scheduler) 的角色存在,它就是做这件事儿的,调度程序使用的算法叫做 调度算法(scheduling algorithm)

    调度算法分类

    针对不同的操作系统环境,也有不同的算法分类,操作系统主要分为下面这几种

    • 批处理操作系统
    • 交互式操作系统
    • 实时操作系统

    下面我们分别来看一下这些操作系统中的算法。

    批处理操作系统中的算法

    设计目标

    批处理系统广泛应用于商业领域,比如用来处理工资单、存货清单、账目收入、账目支出、利息计算、索赔处理和其他周期性作业。在批处理系统中,一般会选择使用非抢占式算法或者周期性比较长抢占式算法。这种方法可以减少线程切换因此能够提升性能。

    交互式用户环境中,因为为了用户体验,所以会避免长时间占用进程,所以需要抢占式算法。由于某个进程出现错误也有可能无限期的排斥其他所有进程。为了避免这种情况,抢占式也是必须的。

    实时系统中,抢占式不是必须的,因为进程知道自己可能运行不了很长时间,通常很快的做完自己的工作并挂起。

    关键指标

    通常有三个指标来衡量系统工作状态:吞吐量、周转时间和 CPU 利用率

    • 吞吐量(throughout) 是系统每小时完成的作业数量。综合考虑,每小时完成 50 个工作要比每小时完成 40 个工作好。
    • 周转时间(Turnaround time) 是一种平均时间,它指的是从一个批处理提交开始直到作业完成时刻为止的平均时间。该数据度量了用户要得到输出所需的平均等待时间。周转时间越小越好。
    • CPU 利用率(CPU utilization) 通常作为批处理系统上的指标。即使如此,CPU 利用率也不是一个好的度量指标,真正有价值的衡量指标是系统每小时可以完成多少作业(吞吐量),以及完成作业需要多长时间(周转时间)。

    下面我们就来认识一下批处理中的算法。

    先来先服务

    很像是先到先得。。。它是一种非抢占式的算法。此算法将按照请求顺序为进程分配 CPU。最基本的,会有一个就绪进程的等待队列。当第一个任务从外部进入系统时,将会立即启动并允许运行任意长的时间。它不会因为运行时间太长而中断。当其他作业进入时,它们排到就绪队列尾部。当正在运行的进程阻塞,处于等待队列的第一个进程就开始运行。当一个阻塞的进程重新处于就绪态时,它会像一个新到达的任务,会排在队列的末尾,即排在所有进程最后。

    这个算法的强大之处在于易于理解编程,在这个算法中,一个单链表记录了所有就绪进程。要选取一个进程运行,只要从该队列的头部移走一个进程即可;要添加一个新的作业或者阻塞一个进程,只要把这个作业或进程附加在队列的末尾即可。这是很简单的一种实现。

    不过,先来先服务也是有缺点的,那就是没有优先级的关系,试想一下,如果有 100 个 I/O 进程正在排队,第 101 个是一个 CPU 密集型进程,那岂不是需要等 100 个 I/O 进程运行完毕才会等到一个 CPU 密集型进程运行,这在实际情况下根本不可能,所以需要优先级或者抢占式进程的出现来优先选择重要的进程运行。

    最短作业优先

    批处理中的第二种调度算法是 最短作业优先(Shortest Job First),我们假设运行时间已知。例如,一家保险公司,因为每天要做类似的工作,所以人们可以相当精确地预测处理 1000 个索赔的一批作业需要多长时间。当输入队列中有若干个同等重要的作业被启动时,调度程序应使用最短优先作业算法

    如上图 a 所示,这里有 4 个作业 A、B、C、D ,运行时间分别为 8、4、4、4 分钟。若按图中的次序运行,则 A 的周转时间为 8 分钟,B 为 12 分钟,C 为 16 分钟,D 为 20 分钟,平均时间内为 14 分钟。

    现在考虑使用最短作业优先算法运行 4 个作业,如上图 b 所示,目前的周转时间分别为 4、8、12、20,平均为 11 分钟,可以证明最短作业优先是最优的。考虑有 4 个作业的情况,其运行时间分别为 a、b、c、d。第一个作业在时间 a 结束,第二个在时间 a + b 结束,以此类推。平均周转时间为 (4a + 3b + 2c + d) / 4 。显然 a 对平均值的影响最大,所以 a 应该是最短优先作业,其次是 b,然后是 c ,最后是 d 它就只能影响自己的周转时间了。

    需要注意的是,在所有的进程都可以运行的情况下,最短作业优先的算法才是最优的。

    最短剩余时间优先

    最短作业优先的抢占式版本被称作为 最短剩余时间优先(Shortest Remaining Time Next) 算法。使用这个算法,调度程序总是选择剩余运行时间最短的那个进程运行。当一个新作业到达时,其整个时间同当前进程的剩余时间做比较。如果新的进程比当前运行进程需要更少的时间,当前进程就被挂起,而运行新的进程。这种方式能够使短期作业获得良好的服务。

    交互式系统中的调度

    交互式系统中在个人计算机、服务器和其他系统中都是很常用的,所以有必要来探讨一下交互式调度

    轮询调度

    一种最古老、最简单、最公平并且最广泛使用的算法就是 轮询算法(round-robin)。每个进程都会被分配一个时间段,称为时间片(quantum),在这个时间片内允许进程运行。如果进程在时间片结束前阻塞或结束,则 CPU 立即进行切换。轮询算法比较容易实现。调度程序所做的就是维护一个可运行进程的列表,就像下图中的 a,当一个进程用完时间片后就被移到队列的末尾,就像下图的 b。

    时间片轮询调度中唯一有意思的一点就是时间片的长度。从一个进程切换到另一个进程需要一定的时间进行管理处理,包括保存寄存器的值和内存映射、更新不同的表格和列表、清除和重新调入内存高速缓存等。这种切换称作 进程间切换(process switch)上下文切换(context switch)

    优先级调度

    轮询调度假设了所有的进程是同等重要的。但事实情况可能不是这样。例如,在一所大学中的等级制度,首先是院长,然后是教授、秘书、后勤人员,最后是学生。这种将外部情况考虑在内就实现了优先级调度(priority scheduling)

    它的基本思想很明确,每个进程都被赋予一个优先级,优先级高的进程优先运行。

    但是也不意味着高优先级的进程能够永远一直运行下去,调度程序会在每个时钟中断期间降低当前运行进程的优先级。如果此操作导致其优先级降低到下一个最高进程的优先级以下,则会发生进程切换。或者,可以为每个进程分配允许运行的最大时间间隔。当时间间隔用完后,下一个高优先级的进程会得到运行的机会。

    可以很方便的将一组进程按优先级分成若干类,并且在各个类之间采用优先级调度,而在各类进程的内部采用轮转调度。下面展示了一个四个优先级类的系统

    它的调度算法主要描述如下:上面存在优先级为 4 类的可运行进程,首先会按照轮转法为每个进程运行一个时间片,此时不理会较低优先级的进程。若第 4 类进程为空,则按照轮询的方式运行第三类进程。若第 4 类和第 3 类进程都为空,则按照轮转法运行第 2 类进程。如果不对优先级进行调整,则低优先级的进程很容易产生饥饿现象。

    最短进程优先

    对于批处理系统而言,由于最短作业优先常常伴随着最短响应时间,所以如果能够把它用于交互式进程,那将是非常好的。交互式进程通常遵循下列模式:等待命令、执行命令、等待命令、执行命令。。。如果我们把每个命令的执行都看作一个分离的作业,那么我们可以通过首先运行最短的作业来使响应时间最短。这里唯一的问题是如何从当前可运行进程中找出最短的那一个进程。

    一种方式是根据进程过去的行为进行推测,并执行估计运行时间最短的那一个。假设每个终端上每条命令的预估运行时间为 T0,现在假设测量到其下一次运行时间为 T1,可以用两个值的加权来改进估计时间,即aT0+ (1- 1)T1。通过选择 a 的值,可以决定是尽快忘掉老的运行时间,还是在一段长时间内始终记住它们。当 a = 1/2 时,可以得到下面这个序列

    可以看到,在三轮过后,T0 在新的估计值中所占比重下降至 1/8。

    有时把这种通过当前测量值和先前估计值进行加权平均从而得到下一个估计值的技术称作 老化(aging)。这种方法会使用很多预测值基于当前值的情况。

    保证调度

    一种完全不同的调度方法是对用户做出明确的性能保证。一种实际而且容易实现的保证是:若用户工作时有 n 个用户登录,则每个用户将获得 CPU 处理能力的 1/n。类似地,在一个有 n 个进程运行的单用户系统中,若所有的进程都等价,则每个进程将获得 1/n 的 CPU 时间。

    彩票调度

    对用户进行承诺并在随后兑现承诺是一件好事,不过很难实现。但是有一种既可以给出预测结果而又有一种比较简单的实现方式的算法,就是 彩票调度(lottery scheduling)算法。

    其基本思想是为进程提供各种系统资源(例如 CPU 时间)的彩票。当做出一个调度决策的时候,就随机抽出一张彩票,拥有彩票的进程将获得该资源。在应用到 CPU 调度时,系统可以每秒持有 50 次抽奖,每个中奖者将获得比如 20 毫秒的 CPU 时间作为奖励。

    如果希望进程之间协作的话可以交换它们之间的票据。例如,客户端进程给服务器进程发送了一条消息后阻塞,客户端进程可能会把自己所有的票据都交给服务器,来增加下一次服务器运行的机会。当服务完成后,它会把彩票还给客户端让其有机会再次运行。事实上,如果没有客户机,服务器也根本不需要彩票。

    可以把彩票理解为 buff,这个 buff 有 15% 的几率能让你产生 速度之靴 的效果。

    公平分享调度

    到目前为止,我们假设被调度的都是各个进程自身,而不用考虑该进程的拥有者是谁。结果是,如果用户 1 启动了 9 个进程,而用户 2 启动了一个进程,使用轮转或相同优先级调度算法,那么用户 1 将得到 90 % 的 CPU 时间,而用户 2 将之得到 10 % 的 CPU 时间。

    为了阻止这种情况的出现,一些系统在调度前会把进程的拥有者考虑在内。在这种模型下,每个用户都会分配一些CPU 时间,而调度程序会选择进程并强制执行。因此如果两个用户每个都会有 50% 的 CPU 时间片保证,那么无论一个用户有多少个进程,都将获得相同的 CPU 份额。

    实时系统中的调度

    实时系统(real-time) 对于时间有要求的系统。实时系统可以分为两类,硬实时(hard real time)软实时(soft real time) 系统,前者意味着必须要满足绝对的截止时间;后者的含义是虽然不希望偶尔错失截止时间,但是可以容忍。在这两种情形中,实时都是通过把程序划分为一组进程而实现的,其中每个进程的行为是可预测和提前可知的。这些进程一般寿命较短,并且极快的运行完成。在检测到一个外部信号时,调度程序的任务就是按照满足所有截止时间的要求调度进程。

    实时系统中的事件可以按照响应方式进一步分类为周期性(以规则的时间间隔发生)事件或 非周期性(发生时间不可预知)事件。一个系统可能要响应多个周期性事件流,根据每个事件处理所需的时间,可能甚至无法处理所有事件。例如,如果有 m 个周期事件,事件 i 以周期 Pi 发生,并需要 Ci 秒 CPU 时间处理一个事件,那么可以处理负载的条件是

    只有满足这个条件的实时系统称为可调度的,这意味着它实际上能够被实现。一个不满足此检验标准的进程不能被调度,因为这些进程共同需要的 CPU 时间总和大于 CPU 能提供的时间。

    实时系统的调度算法可以是静态的或动态的。前者在系统开始运行之前做出调度决策;后者在运行过程中进行调度决策。只有在可以提前掌握所完成的工作以及必须满足的截止时间等信息时,静态调度才能工作,而动态调度不需要这些限制。

    调度策略和机制

    到目前为止,我们隐含的假设系统中所有进程属于不同的分组用户并且进程间存在相互竞争 CPU 的情况。通常情况下确实如此,但有时也会发生一个进程会有很多子进程并在其控制下运行的情况。例如,一个数据库管理系统进程会有很多子进程。每一个子进程可能处理不同的请求,或者每个子进程实现不同的功能(如请求分析、磁盘访问等)。主进程完全可能掌握哪一个子进程最重要(或最紧迫),而哪一个最不重要。但是,以上讨论的调度算法中没有一个算法从用户进程接收有关的调度决策信息,这就导致了调度程序很少能够做出最优的选择。

    解决问题的办法是将 调度机制(scheduling mechanism)调度策略(scheduling policy) 分开,这是长期一贯的原则。这也就意味着调度算法在某种方式下被参数化了,但是参数可以被用户进程填写。让我们首先考虑数据库的例子。假设内核使用优先级调度算法,并提供了一条可供进程设置优先级的系统调用。这样,尽管父进程本身并不参与调度,但它可以控制如何调度子进程的细节。调度机制位于内核,而调度策略由用户进程决定,调度策略和机制分离是一种关键性思路。

    内存管理中的算法

    操作系统在内存管理上也出现过许多算法,这些算法的目标的最终目的都是为了合理分配内存。

    操作系统有两种内存管理方式,一种是位图,一种是 链表

    在使用链表管理内存时,有几种方法的变体

    当按照地址顺序在链表中存放进程和空闲区时,有几种算法可以为创建的进程(或者从磁盘中换入的进程)分配内存。我们先假设内存管理器知道应该分配多少内存,最简单的算法是使用 首次适配(first fit)。内存管理器会沿着段列表进行扫描,直到找个一个足够大的空闲区为止。除非空闲区大小和要分配的空间大小一样,否则将空闲区分为两部分,一部分供进程使用;一部分生成新的空闲区。首次适配算法是一种速度很快的算法,因为它会尽可能的搜索链表。

    首次适配的一个小的变体是 下次适配(next fit)。它和首次匹配的工作方式相同,只有一个不同之处那就是下次适配在每次找到合适的空闲区时就会记录当时的位置,以便下次寻找空闲区时从上次结束的地方开始搜索,而不是像首次匹配算法那样每次都会从头开始搜索。Bays(1997) 证明了下次适配算法的性能略低于首次匹配算法

    另外一个著名的并且广泛使用的算法是 最佳适配(best fit)。最佳适配会从头到尾寻找整个链表,找出能够容纳进程的最小空闲区。最佳适配算法会试图找出最接近实际需要的空闲区,以最好的匹配请求和可用空闲区,而不是先一次拆分一个以后可能会用到的大的空闲区。比如现在我们需要一个大小为 2 的块,那么首次匹配算法会把这个块分配在位置 5 的空闲区,而最佳适配算法会把该块分配在位置为 18 的空闲区,如下

    那么最佳适配算法的性能如何呢?最佳适配会遍历整个链表,所以最佳适配算法的性能要比首次匹配算法差。但是令人想不到的是,最佳适配算法要比首次匹配和下次匹配算法浪费更多的内存,因为它会产生大量无用的小缓冲区,首次匹配算法生成的空闲区会更大一些。

    最佳适配的空闲区会分裂出很多非常小的缓冲区,为了避免这一问题,可以考虑使用 最差适配(worst fit) 算法。即总是分配最大的内存区域(所以你现在明白为什么最佳适配算法会分裂出很多小缓冲区了吧),使新分配的空闲区比较大从而可以继续使用。仿真程序表明最差适配算法也不是一个好主意。

    如果为进程和空闲区维护各自独立的链表,那么这四个算法的速度都能得到提高。这样,这四种算法的目标都是为了检查空闲区而不是进程。但这种分配速度的提高的一个不可避免的代价是增加复杂度和减慢内存释放速度,因为必须将一个回收的段从进程链表中删除并插入空闲链表区。

    如果进程和空闲区使用不同的链表,那么可以按照大小对空闲区链表排序,以便提高最佳适配算法的速度。在使用最佳适配算法搜索由小到大排列的空闲区链表时,只要找到一个合适的空闲区,则这个空闲区就是能容纳这个作业的最小空闲区,因此是最佳匹配。因为空闲区链表以单链表形式组织,所以不需要进一步搜索。空闲区链表按大小排序时,首次适配算法与最佳适配算法一样快,而下次适配算法在这里毫无意义。

    另一种分配算法是 快速适配(quick fit) 算法,它为那些常用大小的空闲区维护单独的链表。例如,有一个 n 项的表,该表的第一项是指向大小为 4 KB 的空闲区链表表头指针,第二项是指向大小为 8 KB 的空闲区链表表头指针,第三项是指向大小为 12 KB 的空闲区链表表头指针,以此类推。比如 21 KB 这样的空闲区既可以放在 20 KB 的链表中,也可以放在一个专门存放大小比较特别的空闲区链表中。

    快速匹配算法寻找一个指定代销的空闲区也是十分快速的,但它和所有将空闲区按大小排序的方案一样,都有一个共同的缺点,即在一个进程终止或被换出时,寻找它的相邻块并查看是否可以合并的过程都是非常耗时的。如果不进行合并,内存将会很快分裂出大量进程无法利用的小空闲区。

    页面置换算法

    页面置换有非常多的算法,下面一起来认识一下

    当发生缺页异常时,操作系统会选择一个页面进行换出从而为新进来的页面腾出空间。如果要换出的页面在内存中已经被修改,那么必须将其写到磁盘中以使磁盘副本保持最新状态。如果页面没有被修改过,并且磁盘中的副本也已经是最新的,那么就不需要进行重写。那么就直接使用调入的页面覆盖需要移除的页面就可以了。

    当发生缺页中断时,虽然可以随机的选择一个页面进行置换,但是如果每次都选择一个不常用的页面会提升系统的性能。如果一个经常使用的页面被换出,那么这个页面在短时间内又可能被重复使用,那么就可能会造成额外的性能开销。在关于页面的主题上有很多页面置换算法(page replacement algorithms),这些已经从理论上和实践上得到了证明。

    下面我们就来探讨一下有哪些页面置换算法。

    最优页面置换算法

    最优的页面置换算法很容易描述,但在实际情况下很难实现。它的工作流程如下:在缺页中断发生时,这些页面之一将在下一条指令(包含该指令的页面)上被引用。其他页面则可能要到 10、100 或者 1000 条指令后才会被访问。每个页面都可以用在该页首次被访问前所要执行的指令数作为标记。

    最优化的页面算法表明应该标记最大的页面。如果一个页面在 800 万条指令内不会被使用,另外一个页面在 600 万条指令内不会被使用,则置换前一个页面,从而把需要调入这个页面而发生的缺页中断推迟。计算机也像人类一样,会把不愿意做的事情尽可能的往后拖。

    这个算法最大的问题时无法实现。当缺页中断发生时,操作系统无法知道各个页面的下一次将在什么时候被访问。这种算法在实际过程中根本不会使用。

    最近未使用页面置换算法

    为了能够让操作系统收集页面使用信息,大部分使用虚拟地址的计算机都有两个状态位,R 和 M,来和每个页面进行关联。每当引用页面(读入或写入)时都设置 R,写入(即修改)页面时设置 M,这些位包含在每个页表项中,就像下面所示

    因为每次访问时都会更新这些位,因此由硬件来设置它们非常重要。一旦某个位被设置为 1,就会一直保持 1 直到操作系统下次来修改此位。

    如果硬件没有这些位,那么可以使用操作系统的缺页中断时钟中断机制来进行模拟。当启动一个进程时,将其所有的页面都标记为不在内存;一旦访问任何一个页面就会引发一次缺页中断,此时操作系统就可以设置 R 位(在它的内部表中),修改页表项使其指向正确的页面,并设置为 READ ONLY 模式,然后重新启动引起缺页中断的指令。如果页面随后被修改,就会发生另一个缺页异常。从而允许操作系统设置 M 位并把页面的模式设置为 READ/WRITE

    可以用 R 位和 M 位来构造一个简单的页面置换算法:当启动一个进程时,操作系统将其所有页面的两个位都设置为 0。R 位定期的被清零(在每个时钟中断)。用来将最近未引用的页面和已引用的页面分开。

    当出现缺页中断后,操作系统会检查所有的页面,并根据它们的 R 位和 M 位将当前值分为四类:

    • 第 0 类:没有引用 R,没有修改 M
    • 第 1 类:没有引用 R,已修改 M
    • 第 2 类:引用 R ,没有修改 M
    • 第 3 类:已被访问 R,已被修改 M

    尽管看起来好像无法实现第一类页面,但是当第三类页面的 R 位被时钟中断清除时,它们就会发生。时钟中断不会清除 M 位,因为需要这个信息才能知道是否写回磁盘中。清除 R 但不清除 M 会导致出现一类页面。

    NRU(Not Recently Used) 算法从编号最小的非空类中随机删除一个页面。此算法隐含的思想是,在一个时钟内(约 20 ms)淘汰一个已修改但是没有被访问的页面要比一个大量引用的未修改页面好,NRU 的主要优点是易于理解并且能够有效的实现

    先进先出页面置换算法

    另一种开销较小的方式是使用 FIFO(First-In,First-Out) 算法,这种类型的数据结构也适用在页面置换算法中。由操作系统维护一个所有在当前内存中的页面的链表,最早进入的放在表头,最新进入的页面放在表尾。在发生缺页异常时,会把头部的页移除并且把新的页添加到表尾。

    先进先出页面可能是最简单的页面替换算法了。在这种算法中,操作系统会跟踪链表中内存中的所有页。下面我们举个例子看一下(这个算法我刚开始看的时候有点懵逼,后来才看懂,我还是很菜)

    • 初始化的时候,没有任何页面,所以第一次的时候会检查页面 1 是否位于链表中,没有在链表中,那么就是 MISS,页面1 进入链表,链表的先进先出的方向如图所示。
    • 类似的,第二次会先检查页面 2 是否位于链表中,没有在链表中,那么页面 2 进入链表,状态为 MISS,依次类推。
    • 我们来看第四次,此时的链表为 1 2 3,第四次会检查页面 2 是否位于链表中,经过检索后,发现 2 在链表中,那么状态就是 HIT,并不会再进行入队和出队操作,第五次也是一样的。
    • 下面来看第六次,此时的链表还是 1 2 3,因为之前没有执行进入链表操作,页面 5 会首先进行检查,发现链表中没有页面 5 ,则执行页面 5 的进入链表操作,页面 2 执行出链表的操作,执行完成后的链表顺序为 2 3 5

    第二次机会页面置换算法

    我们上面学到的 FIFO 链表页面有个缺陷,那就是出链和入链并不会进行 check 检查,这样就会容易把经常使用的页面置换出去,为了避免这一问题,我们对该算法做一个简单的修改:我们检查最老页面的 R 位,如果是 0 ,那么这个页面就是最老的而且没有被使用,那么这个页面就会被立刻换出。如果 R 位是 1,那么就清除此位,此页面会被放在链表的尾部,修改它的装入时间就像刚放进来的一样。然后继续搜索。

    这种算法叫做 第二次机会(second chance)算法,就像下面这样,我们看到页面 A 到 H 保留在链表中,并按到达内存的时间排序。

    a)按照先进先出的方法排列的页面;b)在时刻 20 处发生缺页异常中断并且 A 的 R 位已经设置时的页面链表。

    假设缺页异常发生在时刻 20 处,这时最老的页面是 A ,它是在 0 时刻到达的。如果 A 的 R 位是 0,那么它将被淘汰出内存,或者把它写回磁盘(如果它已经被修改过),或者只是简单的放弃(如果它是未被修改过)。另一方面,如果它的 R 位已经设置了,则将 A 放到链表的尾部并且重新设置装入时间为当前时刻(20 处),然后清除 R 位。然后从 B 页面开始继续搜索合适的页面。

    寻找第二次机会的是在最近的时钟间隔中未被访问过的页面。如果所有的页面都被访问过,该算法就会被简化为单纯的 FIFO 算法。具体来说,假设图 a 中所有页面都设置了 R 位。操作系统将页面依次移到链表末尾,每次都在添加到末尾时清除 R 位。最后,算法又会回到页面 A,此时的 R 位已经被清除,那么页面 A 就会被执行出链处理,因此算法能够正常结束。

    时钟页面置换算法

    即使上面提到的第二次页面置换算法也是一种比较合理的算法,但它经常要在链表中移动页面,既降低了效率,而且这种算法也不是必须的。一种比较好的方式是把所有的页面都保存在一个类似钟面的环形链表中,一个表针指向最老的页面。如下图所示

    当缺页错误出现时,算法首先检查表针指向的页面,如果它的 R 位是 0 就淘汰该页面,并把新的页面插入到这个位置,然后把表针向前移动一位;如果 R 位是 1 就清除 R 位并把表针前移一个位置。重复这个过程直到找到了一个 R 位为 0 的页面位置。了解这个算法的工作方式,就明白为什么它被称为 时钟(clokc)算法了。

    最近最少使用页面置换算法

    最近最少使用页面置换算法的一个解释会是下面这样:在前面几条指令中频繁使用的页面和可能在后面的几条指令中被使用。反过来说,已经很久没有使用的页面有可能在未来一段时间内仍不会被使用。这个思想揭示了一个可以实现的算法:在缺页中断时,置换未使用时间最长的页面。这个策略称为 LRU(Least Recently Used) ,最近最少使用页面置换算法。

    虽然 LRU 在理论上是可以实现的,但是从长远看来代价比较高。为了完全实现 LRU,会在内存中维护一个所有页面的链表,最频繁使用的页位于表头,最近最少使用的页位于表尾。困难的是在每次内存引用时更新整个链表。在链表中找到一个页面,删除它,然后把它移动到表头是一个非常耗时的操作,即使使用硬件来实现也是一样的费时。

    然而,还有其他方法可以通过硬件实现 LRU。让我们首先考虑最简单的方式。这个方法要求硬件有一个 64 位的计数器,它在每条指令执行完成后自动加 1,每个页表必须有一个足够容纳这个计数器值的域。在每次访问内存后,将当前的值保存到被访问页面的页表项中。一旦发生缺页异常,操作系统就检查所有页表项中计数器的值,找到值最小的一个页面,这个页面就是最少使用的页面。

    用软件模拟 LRU

    尽管上面的 LRU 算法在原则上是可以实现的,但是很少有机器能够拥有那些特殊的硬件。上面是硬件的实现方式,那么现在考虑要用软件来实现 LRU 。一种可以实现的方案是 NFU(Not Frequently Used,最不常用)算法。它需要一个软件计数器来和每个页面关联,初始化的时候是 0 。在每个时钟中断时,操作系统会浏览内存中的所有页,会将每个页面的 R 位(0 或 1)加到它的计数器上。这个计数器大体上跟踪了各个页面访问的频繁程度。当缺页异常出现时,则置换计数器值最小的页面。

    NFU 最主要的问题是它不会忘记任何东西,想一下是不是这样?例如,在一个多次(扫描)的编译器中,在第一遍扫描中频繁使用的页面会在后续的扫描中也有较高的计数。事实上,如果第一次扫描的执行时间恰好是各次扫描中最长的,那么后续遍历的页面的统计次数总会比第一次页面的统计次数。结果是操作系统将置换有用的页面而不是不再使用的页面。

    幸运的是只需要对 NFU 做一个简单的修改就可以让它模拟 LRU,这个修改有两个步骤

    • 首先,在 R 位被添加进来之前先把计数器右移一位;
    • 第二步,R 位被添加到最左边的位而不是最右边的位。

    修改以后的算法称为 老化(aging) 算法,下图解释了老化算法是如何工作的。

    我们假设在第一个时钟周期内页面 0 - 5 的 R 位依次是 1,0,1,0,1,1,(也就是页面 0 是 1,页面 1 是 0,页面 2 是 1 这样类推)。也就是说,在 0 个时钟周期到 1 个时钟周期之间,0,2,4,5 都被引用了,从而把它们的 R 位设置为 1,剩下的设置为 0 。在相关的六个计数器被右移之后 R 位被添加到 左侧 ,就像上图中的 a。剩下的四列显示了接下来的四个时钟周期内的六个计数器变化。

    当缺页异常出现时,将置换(就是移除)计数器值最小的页面。如果一个页面在前面 4 个时钟周期内都没有被访问过,那么它的计数器应该会有四个连续的 0 ,因此它的值肯定要比前面 3 个时钟周期内都没有被访问过的页面的计数器小。

    这个算法与 LRU 算法有两个重要的区别:看一下上图中的 e,第三列和第五列

    它们在两个时钟周期内都没有被访问过,在此之前的时钟周期内都引用了两个页面。根据 LRU 算法,如果需要置换的话,那么应该在这两个页面中选择一个。那么问题来了,我萌应该选择哪个?现在的问题是我们不知道时钟周期 1 到时钟周期 2 内它们中哪个页面是后被访问到的。因为在每个时钟周期内只记录了一位,所以无法区分在一个时钟周期内哪个页面最早被引用,哪个页面是最后被引用的。因此,我们能做的就是置换页面3因为页面 3 在周期 0 - 1 内都没有被访问过,而页面 5 却被引用过

    LRU 与老化之前的第 2 个区别是,在老化期间,计数器具有有限数量的位(这个例子中是 8 位),这就限制了以往的访问记录。如果两个页面的计数器都是 0 ,那么我们可以随便选择一个进行置换。实际上,有可能其中一个页面的访问次数实在 9 个时钟周期以前,而另外一个页面是在 1000 个时钟周期之前,但是我们却无法看到这些。在实际过程中,如果时钟周期是 20 ms,8 位一般是够用的。所以我们经常拿 20 ms 来举例。

    工作集页面置换算法

    在最单纯的分页系统中,刚启动进程时,在内存中并没有页面。此时如果 CPU 尝试匹配第一条指令,就会得到一个缺页异常,使操作系统装入含有第一条指令的页面。其他的错误比如 全局变量堆栈 引起的缺页异常通常会紧接着发生。一段时间以后,进程需要的大部分页面都在内存中了,此时进程开始在较少的缺页异常环境中运行。这个策略称为 请求调页(demand paging),因为页面是根据需要被调入的,而不是预先调入的。

    在一个大的地址空间中系统的读所有的页面,将会造成很多缺页异常,因此会导致没有足够的内存来容纳这些页面。不过幸运的是,大部分进程不是这样工作的,它们都会以局部性方式(locality of reference) 来访问,这意味着在执行的任何阶段,程序只引用其中的一小部分。

    一个进程当前正在使用的页面的集合称为它的 工作集(working set),如果整个工作集都在内存中,那么进程在运行到下一运行阶段(例如,编译器的下一遍扫面)之前,不会产生很多缺页中断。如果内存太小从而无法容纳整个工作集,那么进程的运行过程中会产生大量的缺页中断,会导致运行速度也会变得缓慢。因为通常只需要几纳秒就能执行一条指令,而通常需要十毫秒才能从磁盘上读入一个页面。如果一个程序每 10 ms 只能执行一到两条指令,那么它将需要很长时间才能运行完。如果只是执行几条指令就会产生中断,那么就称作这个程序产生了 颠簸(thrashing)

    在多道程序的系统中,通常会把进程移到磁盘上(即从内存中移走所有的页面),这样可以让其他进程有机会占用 CPU 。有一个问题是,当进程想要再次把之前调回磁盘的页面调回内存怎么办?从技术的角度上来讲,并不需要做什么,此进程会一直产生缺页中断直到它的工作集 被调回内存。然后,每次装入一个进程需要 20、100 甚至 1000 次缺页中断,速度显然太慢了,并且由于 CPU 需要几毫秒时间处理一个缺页中断,因此由相当多的 CPU 时间也被浪费了。

    因此,不少分页系统中都会设法跟踪进程的工作集,确保这些工作集在进程运行时被调入内存。这个方法叫做 工作集模式(working set model)。它被设计用来减少缺页中断的次数的。在进程运行前首先装入工作集页面的这一个过程被称为 预先调页(prepaging),工作集是随着时间来变化的。

    根据研究表明,大多数程序并不是均匀的访问地址空间的,而访问往往是集中于一小部分页面。一次内存访问可能会取出一条指令,也可能会取出数据,或者是存储数据。在任一时刻 t,都存在一个集合,它包含所哟欧最近 k 次内存访问所访问过的页面。这个集合 w(k,t) 就是工作集。因为最近 k = 1次访问肯定会访问最近 k > 1 次访问所访问过的页面,所以 w(k,t) 是 k 的单调递减函数。随着 k 的增大,w(k,t) 是不会无限变大的,因为程序不可能访问比所能容纳页面数量上限还多的页面。

    事实上大多数应用程序只会任意访问一小部分页面集合,但是这个集合会随着时间而缓慢变化,所以为什么一开始曲线会快速上升而 k 较大时上升缓慢。为了实现工作集模型,操作系统必须跟踪哪些页面在工作集中。一个进程从它开始执行到当前所实际使用的 CPU 时间总数通常称作 当前实际运行时间。进程的工作集可以被称为在过去的 t 秒实际运行时间中它所访问过的页面集合。

    下面来简单描述一下工作集的页面置换算法,基本思路就是找出一个不在工作集中的页面并淘汰它。下面是一部分机器页表

    因为只有那些在内存中的页面才可以作为候选者被淘汰,所以该算法忽略了那些不在内存中的页面。每个表项至少包含两条信息:上次使用该页面的近似时间和 R(访问)位。空白的矩形表示该算法不需要其他字段,例如页框数量、保护位、修改位。

    算法的工作流程如下,假设硬件要设置 R 和 M 位。同样的,在每个时钟周期内,一个周期性的时钟中断会使软件清除 Referenced(引用)位。在每个缺页异常,页表会被扫描以找出一个合适的页面把它置换。

    随着每个页表项的处理,都需要检查 R 位。如果 R 位是 1,那么就会将当前时间写入页表项的 上次使用时间域,表示的意思就是缺页异常发生时页面正在被使用。因为页面在当前时钟周期内被访问过,那么它应该出现在工作集中而不是被删除(假设 t 是横跨了多个时钟周期)。

    如果 R 位是 0 ,那么在当前的时钟周期内这个页面没有被访问过,应该作为被删除的对象。为了查看是否应该将其删除,会计算其使用期限(当前虚拟时间 - 上次使用时间),来用这个时间和 t 进行对比。如果使用期限大于 t,那么这个页面就不再工作集中,而使用新的页面来替换它。然后继续扫描更新剩下的表项。

    然而,如果 R 位是 0 但是使用期限小于等于 t,那么此页应该在工作集中。此时就会把页面临时保存起来,但是会记生存时间最长(即上次使用时间的最小值)的页面。如果扫描完整个页表却没有找到适合被置换的页面,也就意味着所有的页面都在工作集中。在这种情况下,如果找到了一个或者多个 R = 0 的页面,就淘汰生存时间最长的页面。最坏的情况下是,在当前时钟周期内,所有的页面都被访问过了(也就是都有 R = 1),因此就随机选择一个页面淘汰,如果有的话最好选一个未被访问的页面,也就是干净的页面。

    工作集时钟页面置换算法

    当缺页异常发生后,需要扫描整个页表才能确定被淘汰的页面,因此基本工作集算法还是比较浪费时间的。一个对基本工作集算法的提升是基于时钟算法但是却使用工作集的信息,这种算法称为WSClock(工作集时钟)。由于它的实现简单并且具有高性能,因此在实践中被广泛应用。

    与时钟算法一样,所需的数据结构是一个以页框为元素的循环列表,就像下面这样

    最初的时候,该表是空的。当装入第一个页面后,把它加载到该表中。随着更多的页面的加入,它们形成一个环形结构。每个表项包含来自基本工作集算法的上次使用时间,以及 R 位(已标明)和 M 位(未标明)。

    与时钟算法一样,在每个缺页异常时,首先检查指针指向的页面。如果 R 位被是设置为 1,该页面在当前时钟周期内就被使用过,那么该页面就不适合被淘汰。然后把该页面的 R 位置为 0,指针指向下一个页面,并重复该算法。该事件序列化后的状态参见图 b。

    现在考虑指针指向的页面 R = 0 时会发生什么,参见图 c,如果页面的使用期限大于 t 并且页面为被访问过,那么这个页面就不会在工作集中,并且在磁盘上会有一个此页面的副本。申请重新调入一个新的页面,并把新的页面放在其中,如图 d 所示。另一方面,如果页面被修改过,就不能重新申请页面,因为这个页面在磁盘上没有有效的副本。为了避免由于调度写磁盘操作引起的进程切换,指针继续向前走,算法继续对下一个页面进行操作。毕竟,有可能存在一个老的,没有被修改过的页面可以立即使用。

    原则上来说,所有的页面都有可能因为磁盘I/O 在某个时钟周期内被调度。为了降低磁盘阻塞,需要设置一个限制,即最大只允许写回 n 个页面。一旦达到该限制,就不允许调度新的写操作。

    那么就有个问题,指针会绕一圈回到原点的,如果回到原点,它的起始点会发生什么?这里有两种情况:

    • 至少调度了一次写操作
    • 没有调度过写操作

    在第一种情况中,指针仅仅是不停的移动,寻找一个未被修改过的页面。由于已经调度了一个或者多个写操作,最终会有某个写操作完成,它的页面会被标记为未修改。置换遇到的第一个未被修改过的页面,这个页面不一定是第一个被调度写操作的页面,因为硬盘驱动程序为了优化性能可能会把写操作重排序。

    对于第二种情况,所有的页面都在工作集中,否则将至少调度了一个写操作。由于缺乏额外的信息,最简单的方法就是置换一个未被修改的页面来使用,扫描中需要记录未被修改的页面的位置,如果不存在未被修改的页面,就选定当前页面并把它写回磁盘。

    页面置换算法小结

    我们到现在已经研究了各种页面置换算法,现在我们来一个简单的总结,算法的总结归纳如下

    算法注释
    最优算法不可实现,但可以用作基准
    NRU(最近未使用) 算法和 LRU 算法很相似
    FIFO(先进先出) 算法有可能会抛弃重要的页面
    第二次机会算法比 FIFO 有较大的改善
    时钟算法实际使用
    LRU(最近最少)算法比较优秀,但是很难实现
    NFU(最不经常食用)算法和 LRU 很类似
    老化算法近似 LRU 的高效算法
    工作集算法实施起来开销很大
    工作集时钟算法比较有效的算法
    • 最优算法在当前页面中置换最后要访问的页面。不幸的是,没有办法来判定哪个页面是最后一个要访问的,因此实际上该算法不能使用。然而,它可以作为衡量其他算法的标准。

    • NRU 算法根据 R 位和 M 位的状态将页面氛围四类。从编号最小的类别中随机选择一个页面。NRU 算法易于实现,但是性能不是很好。存在更好的算法。

    • FIFO 会跟踪页面加载进入内存中的顺序,并把页面放入一个链表中。有可能删除存在时间最长但是还在使用的页面,因此这个算法也不是一个很好的选择。

    • 第二次机会算法是对 FIFO 的一个修改,它会在删除页面之前检查这个页面是否仍在使用。如果页面正在使用,就会进行保留。这个改进大大提高了性能。

    • 时钟 算法是第二次机会算法的另外一种实现形式,时钟算法和第二次算法的性能差不多,但是会花费更少的时间来执行算法。

    • LRU 算法是一个非常优秀的算法,但是没有特殊的硬件(TLB)很难实现。如果没有硬件,就不能使用 LRU 算法。

    • NFU 算法是一种近似于 LRU 的算法,它的性能不是非常好。

    • 老化 算法是一种更接近 LRU 算法的实现,并且可以更好的实现,因此是一个很好的选择

    • 最后两种算法都使用了工作集算法。工作集算法提供了合理的性能开销,但是它的实现比较复杂。WSClock 是另外一种变体,它不仅能够提供良好的性能,而且可以高效地实现。

    总之,最好的算法是老化算法和WSClock算法。他们分别是基于 LRU 和工作集算法。他们都具有良好的性能并且能够被有效的实现。还存在其他一些好的算法,但实际上这两个可能是最重要的。

    文件系统中的算法

    文件系统在备份的过程中会使用到算法,文件备份分为逻辑转储和物理转储

    物理转储和逻辑转储

    物理转储的主要优点是简单、极为快速(基本上是以磁盘的速度运行),缺点是全量备份,不能跳过指定目录,也不能增量转储,也不能恢复个人文件的请求。因此句大多数情况下不会使用物理转储,而使用逻辑转储

    逻辑转储(logical dump)从一个或几个指定的目录开始,递归转储自指定日期开始后更改的文件和目录。因此,在逻辑转储中,转储磁盘上有一系列经过仔细识别的目录和文件,这使得根据请求轻松还原特定文件或目录。

    既然逻辑转储是最常用的方式,那么下面就让我们研究一下逻辑转储的通用算法。此算法在 UNIX 系统上广为使用,如下图所示

    待转储的文件系统,其中方框代表目录,圆圈代表文件。黄色的项目表是自上次转储以来修改过。每个目录和文件都被标上其 inode 号。

    此算法会转储位于修改文件或目录路径上的所有目录(也包括未修改的目录),原因有两个。第一是能够在不同电脑的文件系统中恢复转储的文件。通过这种方式,转储和重新存储的程序能够用来在两个电脑之间传输整个文件系统。第二个原因是能够对单个文件进行增量恢复

    逻辑转储算法需要维持一个 inode 为索引的位图(bitmap),每个 inode 包含了几位。随着算法的进行,位图中的这些位会被设置或清除。算法的执行分成四个阶段。第一阶段从起始目录(本例为根目录)开始检查其中所有的目录项。对每一个修改过的文件,该算法将在位图中标记其 inode。算法还会标记并递归检查每一个目录(不管是否修改过)。

    在第一阶段结束时,所有修改过的文件和全部目录都在位图中标记了,如下图所示

    理论上来说,第二阶段再次递归遍历目录树,并去掉目录树中任何不包含被修改过的文件或目录的标记。本阶段执行的结果如下

    注意,inode 编号为 10、11、14、27、29 和 30 的目录已经被去掉了标记,因为它们所包含的内容没有修改。它们也不会转储。相反,inode 编号为 5 和 6 的目录本身尽管没有被修改过也要被转储,因为在新的机器上恢复当日的修改时需要这些信息。为了提高算法效率,可以将这两阶段的目录树遍历合二为一。

    现在已经知道了哪些目录和文件必须被转储了,这就是上图 b 中标记的内容,第三阶段算法将以节点号为序,扫描这些 inode 并转储所有标记为需转储的目录,如下图所示

    为了进行恢复,每个被转储的目录都用目录的属性(所有者、时间)作为前缀。

    最后,在第四阶段,上图中被标记的文件也被转储,同样,由其文件属性作为前缀。至此,转储结束。

    从转储磁盘上还原文件系统非常简单。一开始,需要在磁盘上创建空文件系统。然后恢复最近一次的完整转储。由于磁带上最先出现目录,所以首先恢复目录,给出文件系统的框架(skeleton),然后恢复文件系统本身。在完整存储之后是第一次增量存储,然后是第二次重复这一过程,以此类推。

    尽管逻辑存储十分简单,但是也会有一些棘手的问题。首先,既然空闲块列表并不是一个文件,那么在所有被转储的文件恢复完毕之后,就需要从零开始重新构造。

    另外一个问题是关于链接。如果文件链接了两个或者多个目录,而文件只能还原一次,那么并且所有指向该文件的目录都必须还原。

    还有一个问题是,UNIX 文件实际上包含了许多 空洞(holes)。打开文件,写几个字节,然后找到文件中偏移了一定距离的地址,又写入更多的字节,这么做是合法的。但两者之间的这些块并不属于文件本身,从而也不应该在其上进行文件转储和恢复。

    最后,无论属于哪一个目录,特殊文件,命名管道以及类似的文件都不应该被转储。

    I/O 中的算法

    在 I/O 的磁盘调度中也出现过很多算法,关于寻址和磁盘臂的转动都会对算法产生影响,下面我们就来一起看下

    一般情况下,影响磁盘快读写的时间由下面几个因素决定

    • 寻道时间 - 寻道时间指的就是将磁盘臂移动到需要读取磁盘块上的时间
    • 旋转延迟 - 等待合适的扇区旋转到磁头下所需的时间
    • 实际数据的读取或者写入时间

    这三种时间参数也是磁盘寻道的过程。一般情况下,寻道时间对总时间的影响最大,所以,有效的降低寻道时间能够提高磁盘的读取速度。

    如果磁盘驱动程序每次接收一个请求并按照接收顺序完成请求,这种处理方式也就是 先来先服务(First-Come, First-served, FCFS) ,这种方式很难优化寻道时间。因为每次都会按照顺序处理,不管顺序如何,有可能这次读完后需要等待一个磁盘旋转一周才能继续读取,而其他柱面能够马上进行读取,这种情况下每次请求也会排队。

    通常情况下,磁盘在进行寻道时,其他进程会产生其他的磁盘请求。磁盘驱动程序会维护一张表,表中会记录着柱面号当作索引,每个柱面未完成的请求会形成链表,链表头存放在表的相应表项中。

    一种对先来先服务的算法改良的方案是使用 最短路径优先(SSF) 算法,下面描述了这个算法。

    假如我们在对磁道 6 号进行寻址时,同时发生了对 11 , 2 , 4, 14, 8, 15, 3 的请求,如果采用先来先服务的原则,如下图所示

    我们可以计算一下磁盘臂所跨越的磁盘数量为 5 + 9 + 2 + 10 + 6 + 7 + 12 = 51,相当于是跨越了 51 次盘面,如果使用最短路径优先,我们来计算一下跨越的盘面

    跨越的磁盘数量为 4 + 1 + 1 + 4 + 3 + 3 + 1 = 17 ,相比 51 足足省了两倍的时间。

    但是,最短路径优先的算法也不是完美无缺的,这种算法照样存在问题,那就是优先级 问题,

    这里有一个原型可以参考就是我们日常生活中的电梯,电梯使用一种电梯算法(elevator algorithm) 来进行调度,从而满足协调效率和公平性这两个相互冲突的目标。电梯一般会保持向一个方向移动,直到在那个方向上没有请求为止,然后改变方向。

    电梯算法需要维护一个二进制位,也就是当前的方向位:UP(向上)或者是 DOWN(向下)。当一个请求处理完成后,磁盘或电梯的驱动程序会检查该位,如果此位是 UP 位,磁盘臂或者电梯仓移到下一个更高跌未完成的请求。如果高位没有未完成的请求,则取相反方向。当方向位是 DOWN时,同时存在一个低位的请求,磁盘臂会转向该点。如果不存在的话,那么它只是停止并等待。

    我们举个例子来描述一下电梯算法,比如各个柱面得到服务的顺序是 4,7,10,14,9,6,3,1 ,那么它的流程图如下

    所以电梯算法需要跨越的盘面数量是 3 + 3 + 4 + 5 + 3 + 3 + 1 = 22

    电梯算法通常情况下不如 SSF 算法。

    一些磁盘控制器为软件提供了一种检查磁头下方当前扇区号的方法,使用这样的控制器,能够进行另一种优化。如果对一个相同的柱面有两个或者多个请求正等待处理,驱动程序可以发出请求读写下一次要通过磁头的扇区。

    这里需要注意一点,当一个柱面有多条磁道时,相继的请求可能针对不同的磁道,这种选择没有代价,因为选择磁头不需要移动磁盘臂也没有旋转延迟。

    对于磁盘来说,最影响性能的就是寻道时间和旋转延迟,所以一次只读取一个或两个扇区的效率是非常低的。出于这个原因,许多磁盘控制器总是读出多个扇区并进行高速缓存,即使只请求一个扇区时也是这样。一般情况下读取一个扇区的同时会读取该扇区所在的磁道或者是所有剩余的扇区被读出,读出扇区的数量取决于控制器的高速缓存中有多少可用的空间。

    磁盘控制器的高速缓存和操作系统的高速缓存有一些不同,磁盘控制器的高速缓存用于缓存没有实际被请求的块,而操作系统维护的高速缓存由显示地读出的块组成,并且操作系统会认为这些块在近期仍然会频繁使用。

    当同一个控制器上有多个驱动器时,操作系统应该为每个驱动器都单独的维护一个未完成的请求表。一旦有某个驱动器闲置时,就应该发出一个寻道请求来将磁盘臂移到下一个被请求的柱面。如果下一个寻道请求到来时恰好没有磁盘臂处于正确的位置,那么驱动程序会在刚刚完成传输的驱动器上发出一个新的寻道命令并等待,等待下一次中断到来时检查哪个驱动器处于闲置状态。

    死锁中的算法

    在死锁的处理策略中,其中一点是忽略死锁带来的影响(惊呆了),出现过一个叫做鸵鸟算法

    最简单的解决办法就是使用鸵鸟算法(ostrich algorithm),把头埋在沙子里,假装问题根本没有发生。每个人看待这个问题的反应都不同。数学家认为死锁是不可接受的,必须通过有效的策略来防止死锁的产生。工程师想要知道问题发生的频次,系统因为其他原因崩溃的次数和死锁带来的严重后果。如果死锁发生的频次很低,而经常会由于硬件故障、编译器错误等其他操作系统问题导致系统崩溃,那么大多数工程师不会修复死锁。

    在死锁的检测中出现过一些算法

    每种类型多个资源的死锁检测方式

    如果有多种相同的资源存在,就需要采用另一种方法来检测死锁。可以通过构造一个矩阵来检测从 P1 -> Pn 这 n 个进程中的死锁。

    现在我们提供一种基于矩阵的算法来检测从 P1 到 Pn 这 n 个进程中的死锁。假设资源类型为 m,E1 代表资源类型1,E2 表示资源类型 2 ,Ei 代表资源类型 i (1 <= i <= m)。E 表示的是 现有资源向量(existing resource vector),代表每种已存在的资源总数。

    现在我们就需要构造两个数组:C 表示的是当前分配矩阵(current allocation matrix) ,R 表示的是 请求矩阵(request matrix)。Ci 表示的是 Pi 持有每一种类型资源的资源数。所以,Cij 表示 Pi 持有资源 j 的数量。Rij 表示 Pi 所需要获得的资源 j 的数量

    一般来说,已分配资源 j 的数量加起来再和所有可供使用的资源数相加 = 该类资源的总数。

    死锁的检测就是基于向量的比较。每个进程起初都是没有被标记过的,算法会开始对进程做标记,进程被标记后说明进程被执行了,不会进入死锁,当算法结束时,任何没有被标记过的进程都会被判定为死锁进程。

    上面我们探讨了两种检测死锁的方式,那么现在你知道怎么检测后,你何时去做死锁检测呢?一般来说,有两个考量标准:

    • 每当有资源请求时就去检测,这种方式会占用昂贵的 CPU 时间。
    • 每隔 k 分钟检测一次,或者当 CPU 使用率降低到某个标准下去检测。考虑到 CPU 效率的原因,如果死锁进程达到一定数量,就没有多少进程可以运行,所以 CPU 会经常空闲。

    还有死锁避免的算法

    银行家算法

    银行家算法是 Dijkstra 在 1965 年提出的一种调度算法,它本身是一种死锁的调度算法。它的模型是基于一个城镇中的银行家,银行家向城镇中的客户承诺了一定数量的贷款额度。算法要做的就是判断请求是否会进入一种不安全的状态。如果是,就拒绝请求,如果请求后系统是安全的,就接受该请求。

    比如下面的例子,银行家一共为所有城镇居民提供了 15 单位个贷款额度,一个单位表示 1k 美元,如下所示

    城镇居民都喜欢做生意,所以就会涉及到贷款,每个人能贷款的最大额度不一样,在某一时刻,A/B/C/D 的贷款金额如下

    上面每个人的贷款总额加起来是 13,马上接近 15,银行家只能给 A 和 C 进行放贷,可以拖着 B 和 D、所以,可以让 A 和 C 首先完成,释放贷款额度,以此来满足其他居民的贷款。这是一种安全的状态。

    如果每个人的请求导致总额会超过甚至接近 15 ,就会处于一种不安全的状态,如下所示

    这样,每个人还能贷款至少 2 个单位的额度,如果其中有一个人发起最大额度的贷款请求,就会使系统处于一种死锁状态。

    这里注意一点:不安全状态并不一定引起死锁,由于客户不一定需要其最大的贷款额度,但是银行家不敢抱着这种侥幸心理。

    银行家算法就是对每个请求进行检查,检查是否请求会引起不安全状态,如果不会引起,那么就接受该请求;如果会引起,那么就推迟该请求。

    类似的,还有多个资源的银行家算法,读者可以自行了解。

    展开全文
  • 本文首先对目前家政管理系统开发需技术进行调研,再结合当前家政行业发展的趋势,对该系统提出可行性分析,设计开发出了系统具体功能需求。系统设计采用 B/S 三层模式架构,以JAVA语言工具和MySQL数据库;以及HTML...

    摘 要

    随着我国服务行业水平的不断提高,家政服务者和客户之间的信息互通和管理是既重要又复杂的系统工作。传统家政服务工作方式已无法满足现代信息化社会或全方位诸多个性化服务需求。故开发一个家政服务管理系统,对促进家政服务行业发展颇具实用意义。
    本文首先对目前家政管理系统开发所需技术进行调研,再结合当前家政行业发展的趋势,对该系统提出可行性分析,设计开发出了系统具体功能需求。系统设计采用 B/S 三层模式架构,以JAVA语言工具和MySQL数据库;以及HTML等技术来实现家政服务信息化管理的基本功能。系统主要功能实现了用户信息管理、订单的预约交易评价等服务。其中前台包括客户及家政人员,其中客户可以预约和管理家政服务、审核订单以及评价工作;家政人员可以查看、申请、管理订单及评价用户。后台管理员可以管理所有账户权限与信息认证。该家政服务网站的实现在一定程度上提高了市场竞争力。

    关键词:家政服务;JAVA语言;MySQL数据库;系统开发;B/S模式

    Abstract
    With the continuous improvement of the service industry level inChina, the information exchange and management between domestic service providers and customers is an important and complex system work, and the traditional domestic service work mode can not meet the needs of modern information society or all-round personalized service. Therefore, the development of a domestic service management system, to promote the development of domestic service industry has practical significance.
    This paper first investigates the technology needed for the development of domestic management system, then puts forward the feasibility analysis of the system, and designs and develops the specific functional requirements. The system design adopts B/S three-tier pattern architecture to JAVA language tools and MySQL databases, and HTML technology to realize the basic functions of domestic service information management. The main functions of the system are user information management, order booking transaction evaluation and other services. The front desk includes customers and domestic workers, who can book and manage domestic service, review orders and evaluate the work. Domestic workers can view, apply, manage orders and evaluate users. The background administrator can manage all account permissions and information authentication. The realization of the domestic service website has improved the market competitiveness to some extent.

    Key Words: Domestic service; Java language; MySQL Databases; system development;
    B/S mode;

    目 录
    1 概述 1
    1.1 实用背景意义 1
    1.2 家政现状分析 1
    1.3 论文主体结构 2
    2 系统开发环境与相关技术概述 3
    2.1 系统开发环境 3
    2.1.1 硬件要求 3
    2.1.2 软件要求 3
    2.1.3 系统运行环境需求 3
    2.2 相关技术概述 3
    2.2.1 Java技术 3
    2.2.2 Eclipse简介 4
    2.2.3 B/S架构设计 4
    2.2.4 MySQL数据库简介 5
    3 系统设计分析 6
    3.1 系统可行性分析 6
    3.1.1 经济可行性 6
    3.1.2 技术可行性 6
    3.1.3 实现可行性 6
    3.2 系统需求分析 6
    3.2.1 功能需求分析 6
    3.2.2 系统性能分析 7
    3.3 系统流程设计 7
    3.3.1 用户登入模块 7
    3.3.2 信息修改模块 8
    3.3.3 信息删除流程 …9
    4 系统设计与实现 10
    4.1 系统主要功能 10
    4.2 数据主库设计 12
    4.2.1 数据库概要设计 12
    4.2.2 数据库 E-R图 13
    4.2.3 数据主库表结构 14
    4.3 前台页面展示 17
    4.3.1 注册页面显示 17
    4.3.2 登录显示模块 18
    4.3.3 主要功能模块 20
    4.4 后台管理页面 25
    4.4.1账户管理功能模块…25
    4.4.2身份信息认证模块…25
    5 系统测试与探讨 26
    5.1 系统测试内容 26
    5.2 系统测试方法 26
    5.3 测试结果探讨 26
    5.3.1 用户注册登录模块测试 26
    5.3.2 用户信息管理模块测试 26
    5.3.3 订单管理模块测试 27
    5.3.4 后台管理员模块测试 27
    6 结论与展望 30
    谢辞 31
    参考文献 32
    附录…33

    家政服务管理系统的设计与实现
    1 概 述
    1.1实用背景意义
    家政服务总体是指以家庭和其居住社区为单位的服务对象。通过满足用户的家庭生活或社区事务的劳务需求和优化家庭的社区环境为目标,对整个家庭的运转和发展必不可少的服务性行业[1]。
    随着全球科学技术的快速发展,如今互联网在我国迅速普及,互联网在人们的日常生活和工作中重要部分。随着网络科技水平的不断提高,相关法律也逐渐完善,计算机涉及领域越来越广泛,在社会的不同领域,如家政服务,信息管理,人工智能等方面,已成为不可缺少的重要工具,尤其是在用户的服务体验方面[2]。软件的服务系统出现,使得大量复杂的问题变得简单和容易,同时也带动了消费增长[3]。
    为了适应新形势的发展,互联网家政服务已经日趋成为了新时代家政服务行业普遍形式,并在家政服务行业中发挥高效、便捷的作用,把人们从繁重的工作中解脱出来[4]。在家政服务管理系统中,客户可以在网上根据自己的实际需求进行预约自己的家政服务,并对于家政人员请求的家政订单进行审核。而家政工能够在系统上选择合适的订单以及发送审核、同时系统后台的管理员还能够管理所有的用户信息以及拥有身份认证权限。这样一来,大大减轻了不必要的人力物力浪费以及负担,使家政服务效率得到很大提高,在不受地域的局限同时也让家政服务更加方便[5]。如今,计算机技术的发展达到了相当高的水平。然而,家政服务管理行业软件的开发还处于基础阶段,随着这门技术的不断深化和逐渐提高,远程教育软件系统的功能应该更全面和完善,这对软件开发人员更高的设计要求更高[6]。

    1.2家政现状分析
    随着我国生活水平不断提升,对服务行业的要求也逐渐提高。如今,我国老龄化人口增加,家庭空巢化的现象越来越明显,国民在健康方面也有了较大的认识,因此,我国家政行业得到空前关注,发展迅速。在全球许多发达国家,家政产业已成为服务性行业的重要部门。德国、美国、日本等发达国家已经进入到家政产业繁荣发展阶段,发达国家的高级家政企业目前基础采用校企一体化的模式,即企业本身包含教育培训和经营双重功能。除了经营主业以外,企业还可向五星级以上的酒店培养高素质人才[7]。
    而国内家政市场的需求在近几年同样飞速增长,商务部和国家发改委社会发展司公布的数据显示,2017年中国家政服务行业营业收入达到4500亿元,同比2016年增长26.0%;2015-2017三年年均复合增长率为25.9%,到2020年我国将达到8689亿元。2016年从业家政服务人员2653万人[8],同比2015年增长9.3%。
    随着移动互联网和大数据等信息技术的发展和各路资本的涌入,一种以线上线下相结合的O2O家政模式打破了传统的商业模式,即在商业模式下,上游为家政供应商,中游为家政公司,下游为用户;在新开发的平台模式下,上游为家政供应商和服务提供机构或服务员个人,中游为O3O平台,负责吸引家政服务提供者进驻,下游为家庭客户[9]。结合“互联网+”思维,利用030家政服务模式,为创业者开启发展的道路。同时也产生了一些优秀的家政公司,如51家庭管家、好慷在家和e家洁等。
    利用计算机对日常家政服务数据事务的管理不仅可以节省工作人员大量的时间和精力,而且能保证服务信息记录准确、快速从而提高家政系统的信息管理效率,使得管理更加科学化、规范化;因此家政服务管理系统的开发具有重要意义的。

    1.3论文主体结构
    本文所设计的信息管理系统采用JAVA语言进行编程,并实现家政服务管理系统的设计。设计论文将用六大章对整体设计过程进行阐述,具体的安排如下:
    第1章 概述:主要描述了家政服务信息管理系统的实用背景意义、家政现状分析以及论文主体结构。
    第2章 系统开发环境与相关技术概述:介绍系统开发环境、设计模式、相关技术概述及数据库。
    第3章 设计分析:可行性方案分析,主要包括系统可行性分析和系统需求分析。
    第4章 系统设计与实现:主要包括系统功能主要功能、数据主库设计、及系统各模块功能实现,主要包括管理员方面、客户方面以及家政服务人员方面。
    第5章 系统测试与探讨:对家政服务管理系统进行功能测试,并对其发现的问题进行解决。
    第6章 结论与展望:对系统整体进行总结,以及对未来系统的潜在可能性的展望。

    第2章系统开发环境与相关技术概述
    2.1 系统开发环境
    2.1.1 硬件要求
    硬件要求即家政服务管理系统运行所必须的硬件环境,CPU为2GHz以上的64位处理器。硬件内存要求为4G以上,硬盘空间需要满足16GB或以上。
    2.1.2 软件要求
    软件要求即家政服务管理系统运行所必须的软件支持,主要有Eclipse、MYSQL数据库、操作系统Windows7及以上版本。
    2.1.3 系统运行环境需求
    本系统是基于B/模式的应用程序,后台采用MYSQL数据库进行数据处理,用户只需要通过浏览器界面对程序进行操作即可。计算机配置如图2-1所示。

    图2-1 计算机配置图
    2.2 相关技术概述
    2.2.1 Java技术

    Java是一门面向对象需求的一门语言,它主要是在C++遇到各种问题的时候产生的,它的出现满足了C++语言的不足。它的目的是为了让这门语言变得简单,健壮,更适合开发。这门语言为我们展现的是新开发思想的编程语言。它在开发软件应用程序最为适合,java在某些地方还留存了一些C++的特点,它没有了指针,但是它增加了很多的新特性,比如可以多个继承,目前,java作为目前流行开发语言之一。优点归纳如下:
    (一)面向对象,它把系统的数据和方法作为一个整体,建模层次更高,因所以更为侧重于对象之间的联系。它也适合用于分布式环境。
    (二)分布式,它是一种用于网络应用以实现与和其它计算节点的轻松协作的编程语言。还能够运用本身的类型库、URL地址来进行访问其它对象。
    (三)健壮性,程序在运行过程中出现简单错误,系统会自动处理错误,出现错误也能继续运行。
    (四)多线程,它不仅具有实时响应性,并且还在交互性方面有着卓越的优点,体现在这个方面——对多线程的支持[9]。
    2.2.2 Eclipse简介
    Eclipse 作为当下广泛流行的Java开发工具之一与它的开源以及良好的可扩展性是分不开的尽管就它而言是由框架和服务组成,但由于插件组件的存在使得其可以对开发环境进行构建。Eclipse主要由Eclipse项目、Eclipse技术项目和Eclipse工具项目组成,具体包括JDT、Eclipse Platform 、PDE和CDT四个部分[11]。而这里面的支持开发特性的PDE插件可以与Eclipse 环境生成用具,从而可以无需区分工具功能始终点进而无缝地集成到其他人的用具中,因为Eclipse中的所有内容都是插件,因此所有开发人员都可以在同一位置上部署Eclipse 插件,并给使用者带来具有统一性以及一致的集成开发环境。
    2.2.3 B/S架构设计
    B/S结构是从浏览器到服务器交互模式,这种模式对电脑的要求不高,一般计算机上用其自带浏览器即可[12]。正是由于它这种特性让它具有了跨平台特点,也是得对客户端计算机的配置要求不是那么严格。一般利用Java对于服务器端的开发,都优选使用B/S架构。B/S开发架构由表现层、业务层、持久层三层组成[13]。虽然它们之间相对独立但仍然彼此相关。它们会根据传递过来的参数,对数据库中的数据进行查询,保存等操作。
    B/S的最大优点是无需安装任何特殊软件即可在任何地方进行操作。由于它基于浏览器这种技术,并结合各种脚本语言来进行,所以它开发起来大大提高了开发速度和降低了开发成本[14]。只要有可以访问Internet的电脑,用户就可轻松进行操作,这也使得系统具有良好的扩展性。而对于数据库来说,只需服务器与系统进行连接。而在其他地点登录,只需要专网操作即可。由于现在操作系统基本上都自带浏览器,所以对于客户来说非常方便,服务器端只需要安装数据库即可。B/S结构在不仅让客户机的开支减少,而且也让维护人员的工作量大大减低。当用户在客户端发送请求到后台服务器时,绝大多数流程都会在服务器上开始执行,所以对于客户机和技术维修员来说都减轻了很多负担。

    2.2.4 MySQL 数据库简介
    MYSQL是一个小型的数据库管理系统也是一门成熟的数据源存储技术,它可以轻松的访问数据源,并能够告诉处理数据[15]。MYSQL能够支持多用户同时使用,对其自身而言是开源完全并且免费,同时在它使用相对简单,维护起来十分方便。它还可以快速的记录数条数据,并且能把它储存起来。所以对于开发家政服务管理系统来说是一个非常合适的选择。MYSQL还能够支持多种开发语言,工作在不同的操作系统上MySQL是一个轻量级数据库管理系统[16]。因此可以更快更高性能的对数据进行处理,为整个系统的开发,以及数据的保护提供了一种保障的,可靠的方法,这对于开发者来说无疑是大大减少了程序开发的时间。在本系统中使用了MYSQL数据库,经检验它是可以满足系统的设计使用的。
    3 系统设计分析
    3.1 系统设计分析
    3.1.1 经济可行性
    家政服务管理系统开发是由开发者自行研发并且该系统开发用自己学习的技术并且用到的软件基本上都是开源的,无需购买其余软件。同时系统之前的市场调研工作都是通过开发者自身的努力,遇到重点难点时还可以通过老师同学们的帮助进行解决,无需过多成本投资。

    3.1.2 技术可行性
    本系统基于B/S模式上进行开发,以JAVA语言同时使用eclipse作为系统的开发环境,Java语言可移植性强,上手简易,同时还具备异常处理机制这就为家政服务系统的开发打下了坚实的基础,同时也更加符合人们的需求,方便了新系统的扩展与修改。同时家政服务管理系统结合当前流行的一个数据库技术MYSQL用来作为数据的存储,建立了一个
    数据完整、安全、稳定性强的后台数据库系统。这些软件不仅功能便捷强大而且都可以免费下载,所以家政服务管理系统在技术上是可行的。

    3.1.3 实现可行性
    本系统为一个基于JAVA语言的家政服务管理系统,操作简单便捷,现在普通电脑的硬件、软件基本都能够满足使用条件,该系统主要是界面操作。点击对应的选项,即可进行相应的操作,操作过程与其他管理软件基本相同,用户只需要会网上的基本操作即可即可,适合绝大多数用户,十分方便快捷。综上可知,本课题在经济方面、技术方面、运行方面的条件都是满足的,所以本系统的设计和开发具备都具有可行性。

    3.2 系统需求分析

    3.2.1 功能需求分析
    在满足用户需求的基础上,家政服务管理系统网站通过对市场需求的分析,从而确定系统的功能目标。接着进行系统功能模型与数据库的设计与规划,最后根据各模块功能进行测试进而实现整体结构的设计,最终完成家政服务管理系统网站的最终毕业设计相关文件的编制。本系统分为消费者、家政人员和管理员三种权限的用户。具体功能描述如下。
    (1)用户注册与登录模块。该模块实现消费者及家政人员的注册和登录。
    (2)用户信息管理模块:该模块实现消费者与家政信息修改功能。
    (3)订单管理模块:消费者预约家政服务并发布订单后,家政人员可以申请该订单,当消费者同意家政人员请求后,家政人员完成此订单。
    (4)用户评价模块:当订单完成后消费者可以对订单进行评价
    (5)商家留言模块:用户对商家进行留言
    (6)管理员模块:管理员可以实现所有用户账号权限修改及对消费者、家政人员、商家信息进行认证管理
    3.2.2 系统性能分析
    (1)安全性:当用户进行登录时密码设置上限为20位,并且会有验证码校验登录信息,再加上后台数据库的备份功能,保障了系统的安全性。
    (2)可扩展性:家政管理系统的开发功能仍需不断改进才能带给用户更好的体验,这就要求程序具备相应的可扩展性。
    (3)敏捷性:本次家政系统采用Mysql数据库进行开发,提高了处理数据速度,可以让用户可以在极短的时间内得到操作反馈。
    (4)易用性:系统操作简单,适用于大多年龄段的人群,即使是没有什么上网经验的新手也能够快速上手,有良好的交互功能。消费者可通过浏览家政服务界面,对自己需要的服务进行预约交易。

    3.3 系统流程设计

    3.3.1 用户登录模块

    系统开发完成之后会给消费者及家政人员提供注册与登录入口,在这个界面用户输入的信息会得到验证,通过验证之后才能进去家政服务管理系统及后台管理人员的访问主界面,系统登录执行流程如图3-1所示。
    在这里插入图片描述
    3.3.2 信息修改模块
    系统用户添加信息时,系统会自动编号。如果添加信息为消费者信息则将其信息添加到后台数据库的customer表中,家政人员信息变更在housekeeper表中,后台管理员信息输入则信息存储在admin表。系统会对输入的数据进行判断是否合法,合法则可以写入。否则用户无法修改当前数据,流程图如图3-2所示。
    在这里插入图片描述
    图3-2 数据增加流程图

    3.3.3 信息删除流程
    当系统用户发起删除信息时,后台数据库根据所存储的数据相关信息进行校验规则对该数据进行删除,当用户发起删除信息的流程时,后台的数据库按照存储数据的相关信息,进行校验,该数据符合删除的原则后,再进行删除否则不删除数据。这样以来就无需后台数据库对其对应的数据相关信息进行维护,而且也无需应用系统访问进行数据删除校验从而提高对删除的数据的维护。当信息删除时只能通过管理员在后台数据库从新添加数据信息,否则无法恢复。数据删除流程图如下图3-3所示。
    在这里插入图片描述
    图3-3 数据删除流程图
    4 系统设计与实现
    4.1 系统主要功能
    本系统采用自上往下的开发方式。了解客户的基本需求后,主要功能可以定位如下:本课题要求设计出一套家政服务管理系统,系统可以分为两部分:前台界面和后台管理界面。前台界面由消费者以及家政人员使用,消费者功能包括登录、预约自己的家政服务订单、管理自己的家政服务订单、审核家政服务订单的申请以及确认订单等功能模块,家政人员包括登录、查看所有消费者发布的家政服务订单、申请服务订单、管理自己申请家政服务订单和用户评价等模块;后台管理界面由系统管理员操作,维护系统安全,管理员主要实现了家政管理系统中所有用户管理和认证管理等功能。系统功能模块结构图如图4-1所示。
    在这里插入图片描述
    图4-1 系统整体功能结构图

    。。。。。。。。。。。。
    。。。。。。。。。。。。。
    。。。。。。。。。。。。。
    全部论文内容点击:下载连接

    展开全文
  • 学生成绩管理系统

    千次阅读 2021-06-23 00:53:32
    学生成绩管理系统基于Javaweb来完成. ** ***2.编译工具及环境 ** 2.1Ecilpse 2.2Apache Tomcat v8.5 2.3MySQL Workbench 6.3 CE**** ** 2.4编程语言** ** Java,html,css,javascipt** 3.需求分析 3.1面向人群 学校...
  • 题目描述:请求分页系统中的置换算法 1.通过如下方法产生一指令序列,共 320 条指令。 A. 在[1,32k-2]的指令地址之间随机选取一起点M,访问 M; B. 顺序访问M+1; C. 在[0,M-1]中随机选取M1,访问 M1; D. 顺序...
  • 大家好,我是小林。 昨天有位关注我一年的读者找我,他去年关注我公众后,开始...这里先给大家分享些计算机必读书籍,获取方式:计算机必读书籍(含下载方式),包含数据结构与算法、操作系统、计算机网络、数据库、L
  • 文章目录1 虚拟内存1.1 传统存储管理方式的特征、缺点1.2 局部性原理1.3 虚拟内存主要特征1.4 如何实现虚拟内存技术1.5 虚拟内存的基本概念小结...地址变换机构2.4 请求分页管理方式小结3 页面置换算法3.1 最佳置换算法...
  • 【C语言】学籍管理系统

    万次阅读 多人点赞 2018-06-03 22:34:28
    C语言 – 学籍管理系统 功能简介 链表实现基本的创建增删改查。 成绩分析,链表的冒泡排序。 分管理员,老师,学生三端管理,密码的修改,加密。 分班级管理老师学生。 方框界面,↑↓键控制,ENTER...
  • 程序用C语言实现操做系统中的内存管理,内存分配算法包括FF,BF,WF三种
  • C语言图书管理系统设计报告

    万次阅读 多人点赞 2017-06-20 17:37:54
    源代码:https://blog.csdn.net/k_young1997/article/details/73480766 XXXX大学 C语言课程设计报告 ...题 目 图书管理系统设计 专业班级 XXXX级计算机科学与技术本科X班 组 别 计科第...
  • 文章目录前言知识总览1、首次适应算法2、最佳适应算法3、最坏适应算法4、邻近适应算法知识回顾与重要考点 前言 此篇文章是我在B站学习时做的笔记,大部分图片都是课件老师的PPT,方便复习用。此篇文章仅供学习参考...
  • 实验三 请求调页存储管理方式的模拟 1.实验目的 通过对页面、页表、地址转换和页面置换过程的模拟,加深对请求调页系统的原理和实现过程的理解。 2.实验内容 (1)假设每个页面中可存放10条指令,分配给作业的内存...
  • 2 相关技术介绍及系统环境开发条件 5 2.1相关技术介绍 5 2.2系统环境开发条件 6 3 系统的需求分析与设计 7 3.1可行性分析 7 3.2需求分析 7 3.2.1系统总体概述 8 3.2.2功能性需求 8 3.2.3非功能性需求 9 3.2.4流程图...
  • 在虚存管理中。当发生缺页中断时,进行页面的换入操作。对于一些不能够被换出的内存,通常采用页面锁定的方式,在页表中添加锁定标志位(lock bit)以区分该页是否是常驻内存。当内存满需要换出时,为了减少缺页频率...
  • 电商后台管理系统(一)

    千次阅读 2021-05-03 14:17:04
    后台管理系统git地址:https://gitee.com/kk23851 一.项目大体架构 二.用户登录 用户登录页面 思路:用Element表单验证完成以后,把数据存储到本地 用户登录代码位置如图: 三.用户管理 用户列表页面 绘制用户列表...
  • 操作系统中常见算法

    千次阅读 2018-08-27 13:54:36
    一、五种进程调度算法 1、时间片轮转调度算法(RR):给每个进程固定的执行时间,根据进程...适用于分时系统。 2、先来先服务调度算法(FCFS):根据进程到达的先后顺序执行进程,不考虑等待时间和执行时间,会...
  • 操作系统——页面置换算法

    千次阅读 2019-05-13 14:32:34
    操作系统将内存按照页的进行管理,在需要的时候才把进程相应的部分调入内存。当产生缺页中断时,需要选择一个页面写入。如果要换出的页面在内存中被修改过,变成了“脏”页面,那就需要先写会到磁盘。页面置换算法,...
  • 可变分区管理分配算法

    千次阅读 2020-07-07 08:27:40
    1、最先(首次)适应分配算法 空闲分区通常按地址从小到大排列,分配第一个满足长度要求地空闲区。 首地址 大小 100k 128k 800k 200k 1300k 700k 第一个请求188k,第二个请求138k 首先在首地址为800k的...
  • 操作系统-动态分区分配算法详解

    千次阅读 2020-04-18 18:02:03
    首次适应算法(First Fit)2.最佳适应算法(Best Fit)3.最坏适应算法(Worst Fit)4. 邻近适应算法(Next Fit) 概览 首次适应算法(First Fit) 最佳适应算法(Best Fit) 最坏适应算法(Worst Fit) 邻近适应算法(Next...
  • 摘要:人脸检测与识别是机器视觉领域最热门的研究方向之一,本文详细介绍博主自主设计的一款基于深度学习的人脸识别与管理系统。博文给出人脸识别实现原理的同时,给出Python的人脸识别实现代码以及PyQt设计的UI界面...
  • Web管理员后端界面展示 电影推荐系统——用户界面展示 本章介绍具体实现过程。 普通用户 在普通用户网页实现中,重点在于如何根据给定数据生成多个网页,本设计采用Flask自带的jinja模板渲染模块实现。其次是评论...
  • 操作系统实验二 银行家算法

    千次阅读 2020-06-05 16:11:43
    实验二 银行家算法 一、实验目的 1、了解什么是操作系统安全状态和不安全状态;...四、实验原理 实验中用到系统调用函数(包括实验原理中介绍的和自己采用的),实验步骤, 进程申请资源时,系统通...
  • 算法入门)栈和队列-停车场管理系统

    千次阅读 多人点赞 2014-11-07 23:13:22
    通过停车场管理的程序设计,帮助学生熟练掌握栈和队列的基本操作及用栈与队列解决具体问题的基本方法。 二、实验内容 设停车场是一个可以停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。 汽车在停车场内按...
  • 基于java的学生宿舍管理系统(含源文件)

    万次阅读 多人点赞 2021-03-05 19:51:49
    学生宿舍管理系统 摘 要 随着电脑的普及与使用,现在的管理也提升了一个档次,渐渐实现了无纸化办公,即从原来的人工记录管理模式转变为电脑一体化管理。高校是科研的阵地,后勤的宿舍管理也应该一改传统的人工...
  • 1、了解什么是操作系统安全状态和不安全状态; 2、了解如何避免系统死锁; 3、理解银行家算法是一种最有代表性的避免死锁的算法,掌握其实现原理及实现过程。 二、 实验环境 Windows、g++ 三、 实验内容 根据银行家...
  • 数学建模算法学习——各类模型算法汇总

    万次阅读 多人点赞 2019-09-08 14:28:50
    数据分析类算法一览 100个经典动态规划方程 优化问题 线性规划 简介:线性规划的目标函数可以是求最大值,也可以是求最小值,约束条件的不等号可以是小于号也可以是大于号。为了避免这种形式多样性带来的不便,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 166,618
精华内容 66,647
关键字:

管理系统所用到的算法