实验三 存储管理

一、实验目的

存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常用的虚拟存储管理技术。本实验的目的是通过请求页式管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。

二、实验内容

1、通过计算不同算法的命中率比较算法的优劣。同时也考虑了用户内存容量对命中率的影响。

2、页面失效次数为每次访问相应指令时,该指令所对应的页不在内存中的次数。

3、在本实验中,假定页面大小为 1k,用户虚存容量为 32k,用户内存容量为 4 页到 32 页。

三、实验要求

1、计算并输出下属算法在不同内存容量下的命中率。

1)先进先出的算法(FIFO);

2)最近最少使用算法(LRU);

2、address通过随机数产生一个指令序列,共320条指令。

指令的地址按下述原则生成:

1)50%的指令是顺序执行的

2)25%的指令是均匀分布在前地址部分

3)25%的指令是均匀分布在后地址部分

四、实验过程

具体的实施方法是:

1)在[0,319]的指令地址之间随机选取一起点m;

2)顺序执行一条指令,即执行地址为m+1的指令;

3)在前地址[0,m+1]中随机选取一条指令并执行,该指令的地

址为 m1;

4)顺序执行一条指令,地址为m1+1的指令

5)在后地址[m1+2,319]中随机选取一条指令并执行;

6)重复上述步骤 1)~5),直到执行320次指令

五、实验分析与实现

1、避免伪随机数生成使用c++的time.h的库

#include <time.h>

使用srand((unsigned)time(NULL))及rand()实现

Address::Address()
{
    cout<<"Start memory management."<<'\n';
    cout<<"Producing address flow, wait for while, please."<<'\n';
    int j=0;
    flag=true;
    srand((unsigned)time(NULL));
    
    /* 生成指令序列 */
    while(j<320)
    {
        /* 在[0,319]的指令地址之间随机选取一起点 m; */
        m=rand()%320;
        /* 顺序执行一条指令,即执行地址为 m+1 的指令 */
        order[j]=m+1;
        cout<<order[j++]<<'\t';
        /* 在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为 m1 */
        m1=rand()%(m+2);
        /* 顺序执行一条指令,地址为 m1+1 的指令 */
        order[j]=m1+1;
        cout<<order[j++]<<'\t';
        /* 在后地址[m’+2,319]中随机选取一条指令并执行 */
        order[j]=(m1+2)+(rand()%(320-m1-2));
        cout<<order[j++]<<'\t';
    }
}

2、队列的数据结构的实现,使用模板类实现队列

linkqueue.h文件:

#include <iostream>
using namespace std;

template <class T>
struct Node
{
    T data;
    Node<T> *next;
};

template <class T>
class LinkQueue
{
public:
    LinkQueue(); /* 构造函数,初始化空的链队列 */
    ~LinkQueue(); /* 析构函数,释放链队中各结点的存储空间 */
    void EnQueue(T x); /* 将元素x入队 */
    T DeQueue(); /* 将队头元素出队 */
    void DeQueue(T x); /* 将队头元素出队 */
    void SetNullQueue(); /* 队列清空 */
    bool Empty(); /* 判断队列是否为空 */
    bool Exist(T x); /* 判断队列里是否存在这个页面 */
    int GetLength(); /* 返回队列的长度 */
//    friend void FIFO(); /* 先进先出算法 */
//    friend void LRU(); /* 最近最久未使用算法 */

private:
    Node<T> *front, *rear;
    int length;/* 计算队列长度 */
    int m,m1;/* 起点 m,m1 */
    int S; /* 算法号 */
    bool flag; /* 判断输入的算法号是否符合要求 */
    int Msize=2; /* 用户内存空间 */
};

template <class T>
LinkQueue<T>::LinkQueue()
{
    Node <T> *s;
    s=new Node<T>;
    s->next=NULL;
    front=rear=s;
}

template <class T>
LinkQueue<T>::~LinkQueue()
{
    while(front)
    {
        Node <T> *p;
        p=front->next;
        delete front;
        front=p;
    }
}

/* 入队函数 */
template<class T>
void LinkQueue<T>::EnQueue (T x)
{
    Node<T> *s;
    s=new Node<T> ; /* 生成结点s */
    s->data=x;
    s->next =NULL;
    rear->next=s ; /* 将结点s接队尾 */
    rear=s ; /* 队尾指针指向新队尾结点 */
    length++;
}

template <class T>
T LinkQueue<T>:: DeQueue ()
{
    Node<T>*p;
    T x;
    if(rear==front)
        throw "下溢";
    p=front->next;
    x=p->data; /* 暂存队头元素 */
    front->next=p->next; /* 将队头元素所在结点摘链 */
    if (p->next==NULL)
        rear=front; /* 判断出队前队列长度是否为1 */
    length--;
    delete p;
    return x;
}

template <class T>
void LinkQueue<T>::DeQueue (T x)
{
    Node<T>*p,*s;
    if(rear==front)
        throw "下溢";
    p=front;
    s=front->next;
    while(p!=rear)
    {
        if(s->data==x)
        {
            p->next=s->next; /* 将元素所在结点摘链 */
        }
        s=s->next;
        p=p->next;
    }
    if (p->next==rear)
        rear=front; /* 判断出队前队列长度是否为1 */
    length--;
    delete p,s;
}

/* 判断链队列是否为空函数 */
template <class T>
bool LinkQueue<T>::Empty()
{
    if(front==rear)
        return 1;
    else
        return 0;
}

/* 队列清空函数 */
template <class T>
void LinkQueue<T>::SetNullQueue ()
{
    rear = front;
}

/* 返回队列长度 */
template <class T>
int LinkQueue<T>::GetLength ()
{
    return length;
}

/* 判断队列里是否存在这个页面 */
template <class T>
bool LinkQueue<T>::Exist(T x)
{
    Node<T> *p;
    if(rear==front)
        throw "下溢";
    p=front->next;
    while(p!=rear->next)
    {
        if(p->data==x)
        {
            return 1;
        }
        else
            p=p->next;
    }
    return 0;
}

3、实现最近最久未使用算法

步骤:

判断页面是否在队列物理块里面。若不存在则先判断是否29个物理块全部被占用,若未被全部占用,直接将此页插在队列最后面,若全部被占用,则将先进队列的队头元素出队,再将此页面入队,缺页次数+1;若存在,将此页面先出队,再在最后入队,将最近最久未使用的页面放在队首。

/* 最近最久未使用算法 */
void LRU(int order[],int size)
{
    int number=0; /* 初始化缺页次数 */
    LinkQueue<int> q;

    /* 执行320条指令序列 */
    for(int i=0;i<size;i++)
    {
        /* 如果队列为空,则将此页面放入物理块的队列里 */
        if(q.Empty())
        {
            q.EnQueue(order[i]);
            number++;
        }
        else
        {
            /* 判断页面是否在队列物理块里面
             * 若不存在则先判断是否29个物理块全部被占用,
             * 若未被全部占用,直接将此页插在队列最后面,
             * 若全部被占用,则将先进队列的队头元素出队,再将此页面入队
             * 缺页次数+1;
             * 若存在,将此页面先出队,再在最后入队,将最近最久未使用的页面放在队首*/
            if(!q.Exist(order[i]))
            {
                if(q.GetLength()<=29)
                    q.EnQueue(order[i]);
                else
                {
                    q.DeQueue();
                    q.EnQueue(order[i]);
                }
                number++;
            }
            else if(q.Exist(order[i]))
            {
                q.DeQueue(order[i]);
                q.EnQueue(order[i]);
            }
        }
    }
    /* 记录命中率 */
    double rate=1-number/320.0;
    cout<<"LRU算法命中率: "<<rate<<'\t';
}

六、实验过程中的问题及对应思考

1.如何实现先进先出算法?

解决:使用数据结构队列

2.模板类实例定义无效

解决:将模板类.cpp文件内容加到.h文件中。

思考:模板类的实现,脱离具体的使用,是无法单独的编译的;把声明和实现分开的做法也是不可取的,必须把实现全部写在头文件里面。或者在类的定义源文件中使用关键字export,然后其他文件使用时只需包含类的定义头文件就可以。

3.如何利用已有的代码(已实现FIFC算法)实现LRU算法

解决:将最近使用的页面出队,插入到队列最后面,最近未使用的页面排在队列的最前面

七、附录

address.h文件内容:
/* c++头文件 */
#include <iostream>
#include <time.h>

using namespace std;

/* 指令类,生成指令序列 */
class Address
{
public:
    Address();/* 生成指令序列 */
    int Judge(int m);/* 判断输入的算法号是否在[1,4] */
    void GetOrder(int a[]);
private:
    int m,m1;/* 起点 m,m1 */
    int order[320];/* 指令序列 */
    int S; /* 算法号 */
    bool flag; /* 判断输入的算法号是否符合要求 */
};

algorithm.h文件
/* 先进先出算法 */
void FIFO(int order[],int size);
/* 最近最久未使用算法 */
void LRU(int order[],int size);
linkqueue.h文件:
#include <iostream>
using namespace std;

template <class T>
struct Node
{
    T data;
    Node<T> *next;
};

template <class T>
class LinkQueue
{
public:
    LinkQueue(); /* 构造函数,初始化空的链队列 */
    ~LinkQueue(); /* 析构函数,释放链队中各结点的存储空间 */
    void EnQueue(T x); /* 将元素x入队 */
    T DeQueue(); /* 将队头元素出队 */
    void DeQueue(T x); /* 将队头元素出队 */
    void SetNullQueue(); /* 队列清空 */
    bool Empty(); /* 判断队列是否为空 */
    bool Exist(T x); /* 判断队列里是否存在这个页面 */
    int GetLength(); /* 返回队列的长度 */
//    friend void FIFO(); /* 先进先出算法 */
//    friend void LRU(); /* 最近最久未使用算法 */

private:
    Node<T> *front, *rear;
    int length;/* 计算队列长度 */
    int m,m1;/* 起点 m,m1 */
    int S; /* 算法号 */
    bool flag; /* 判断输入的算法号是否符合要求 */
    int Msize=2; /* 用户内存空间 */
};

template <class T>
LinkQueue<T>::LinkQueue()
{
    Node <T> *s;
    s=new Node<T>;
    s->next=NULL;
    front=rear=s;
}

template <class T>
LinkQueue<T>::~LinkQueue()
{
    while(front)
    {
        Node <T> *p;
        p=front->next;
        delete front;
        front=p;
    }
}

/* 入队函数 */
template<class T>
void LinkQueue<T>::EnQueue (T x)
{
    Node<T> *s;
    s=new Node<T> ; /* 生成结点s */
    s->data=x;
    s->next =NULL;
    rear->next=s ; /* 将结点s接队尾 */
    rear=s ; /* 队尾指针指向新队尾结点 */
    length++;
}

template <class T>
T LinkQueue<T>:: DeQueue ()
{
    Node<T>*p;
    T x;
    if(rear==front)
        throw "下溢";
    p=front->next;
    x=p->data; /* 暂存队头元素 */
    front->next=p->next; /* 将队头元素所在结点摘链 */
    if (p->next==NULL)
        rear=front; /* 判断出队前队列长度是否为1 */
    length--;
    delete p;
    return x;
}

template <class T>
void LinkQueue<T>::DeQueue (T x)
{
    Node<T>*p,*s;
    if(rear==front)
        throw "下溢";
    p=front;
    s=front->next;
    while(p!=rear)
    {
        if(s->data==x)
        {
            p->next=s->next; /* 将元素所在结点摘链 */
        }
        s=s->next;
        p=p->next;
    }
    if (p->next==rear)
        rear=front; /* 判断出队前队列长度是否为1 */
    length--;
    delete p,s;
}

/* 判断链队列是否为空函数 */
template <class T>
bool LinkQueue<T>::Empty()
{
    if(front==rear)
        return 1;
    else
        return 0;
}

/* 队列清空函数 */
template <class T>
void LinkQueue<T>::SetNullQueue ()
{
    rear = front;
}

/* 返回队列长度 */
template <class T>
int LinkQueue<T>::GetLength ()
{
    return length;
}

/* 判断队列里是否存在这个页面 */
template <class T>
bool LinkQueue<T>::Exist(T x)
{
    Node<T> *p;
    if(rear==front)
        throw "下溢";
    p=front->next;
    while(p!=rear->next)
    {
        if(p->data==x)
        {
            return 1;
        }
        else
            p=p->next;
    }
    return 0;
}

address.cpp内容
#include "address.h"

Address::Address()
{
    cout<<"Start memory management."<<'\n';
    cout<<"Producing address flow, wait for while, please."<<'\n';
    int j=0;
    flag=true;
    srand((unsigned)time(NULL));
    
    /* 生成指令序列 */
    while(j<320)
    {
        /* 在[0,319]的指令地址之间随机选取一起点 m; */
        m=rand()%320;
        /* 顺序执行一条指令,即执行地址为 m+1 的指令 */
        order[j]=m+1;
        cout<<order[j++]<<'\t';
        /* 在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为 m1 */
        m1=rand()%(m+2);
        /* 顺序执行一条指令,地址为 m1+1 的指令 */
        order[j]=m1+1;
        cout<<order[j++]<<'\t';
        /* 在后地址[m’+2,319]中随机选取一条指令并执行 */
        order[j]=(m1+2)+(rand()%(320-m1-2));
        cout<<order[j++]<<'\t';
    }
}

int Address::Judge(int m)
{
    S=m;
    /* 判断输入的算法号是否在[1,4] */
    switch(S)
    {
    case 1:
        flag=true;
        break;
    case 2:
        flag=true;
        break;
    case 3:
        flag=true;
        cout<<"Wait for this algorithm to be written"<<'\n';
        break;
    case 4:
        flag=true;
        cout<<"Wait for this algorithm to be written"<<'\n';
        break;
    default:
        cout<<"there is not the algorithm in the program"<<'\n';
        flag=false;
    }
    return flag;
}

void Address::GetOrder(int a[])
{
    for(int i=0;i<320;i++)
    {
        a[i]=order[i];
    }
}

algorithm.cpp内容
#include "algorithm.h"
#include "linkqueue.h"

/* 先进先出算法 */
void FIFO(int order[],int size)
{
    int number=0;
    LinkQueue<int> q;
    /* 执行320条指令序列 */
    for(int i=0;i<size;i++)
    {
        /* 如果队列为空,则将此页面放入物理块的队列里 */
        if(q.Empty())
        {
            q.EnQueue(order[i]);
            number++;
        }
        else
        {
            /* 判断页面是否在队列物理块里面
             * 若不存在则先判断是否29个物理块全部被占用,
             * 若未被全部占用,直接将此页插在队列最后面,
             * 若全部被占用,则将先进队列的队头元素出队,再将此页面入队
             * 缺页次数+1;
             * 若存在,则继续进入下一个页面*/
            if(!q.Exist(order[i]))
            {
                if(q.GetLength()<=29)
                    q.EnQueue(order[i]);
                else
                {
                    q.DeQueue();
                    q.EnQueue(order[i]);
                }
                number++;
            }
            else if(q.Exist(order[i]))
                continue;
        }
    }
    double rate=1-number/320.0;
    cout<<"FIFO算法命中率: "<<rate<<'\t';
}

/* 最近最久未使用算法 */
void LRU(int order[],int size)
{
    int number=0; /* 初始化缺页次数 */
    LinkQueue<int> q;

    /* 执行320条指令序列 */
    for(int i=0;i<size;i++)
    {
        /* 如果队列为空,则将此页面放入物理块的队列里 */
        if(q.Empty())
        {
            q.EnQueue(order[i]);
            number++;
        }
        else
        {
            /* 判断页面是否在队列物理块里面
             * 若不存在则先判断是否29个物理块全部被占用,
             * 若未被全部占用,直接将此页插在队列最后面,
             * 若全部被占用,则将先进队列的队头元素出队,再将此页面入队
             * 缺页次数+1;
             * 若存在,将此页面先出队,再在最后入队,将最近最久未使用的页面放在队首*/
            if(!q.Exist(order[i]))
            {
                if(q.GetLength()<=29)
                    q.EnQueue(order[i]);
                else
                {
                    q.DeQueue();
                    q.EnQueue(order[i]);
                }
                number++;
            }
            else if(q.Exist(order[i]))
            {
                q.DeQueue(order[i]);
                q.EnQueue(order[i]);
            }
        }
    }
    /* 记录命中率 */
    double rate=1-number/320.0;
    cout<<"LRU算法命中率: "<<rate<<'\t';
}

main.cpp内容
#include "address.h"
#include "algorithm.h"
#include "linkqueue.h"

int main()
{
    int order[320];/* 指令 */
    int S; /* 算法号 */
    Address ad;
    cout<<"There are algorithms in the program"<<'\n';
    cout<<"\t1、 Optimization algorithm"<<'\n';
    cout<<"\t2、 Least recently used algorithm"<<'\n';
    cout<<"\t3、 First in first out algorithm"<<'\n';
    cout<<"\t4、 Least frequently used algorithm"""<<'\n';
    cout<<"     Select an algorithm number, please."<<endl;
    while(true)
    {
        cin>>S;
        if(ad.Judge(S))
        {
            break;
        }
    }
    ad.GetOrder(order);
    /* 判断输入的算法号是否在[1,4] */
    switch(S)
    {
    case 1:
        cout<<"1";
        FIFO(order,320);
        break;
    case 2:
        cout<<"2";
        LRU(order,320);
        break;
    case 3:
        cout<<"3";
        break;
    case 4:
        cout<<"4";
        break;
    default:
        cout<<"there is not the algorithm in the program"<<'\n';
    }
}


  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整虚拟存储管理器实验报告!一、实验目的请求页式虚存管理是常用的虚拟存储管理方案之一。通过请求页式虚存管理中对页面置换算法的模拟,有助于理解虚拟存储技术的特点,并加深对请求页式虚存管理的页面调度算法的理解。二、实验环境 Turbo C 2.0/3.0或VC++6.0、实验内容本实验要求使用C语言编程模拟一个拥有若干个虚页的进程在给定的若干个实页中运行、并在缺页中断发生时分别使用FIFO和LRU算法进行页面置换的情形。其中虚页的个数可以事先给定(例如10个),对这些虚页访问的页地址流(其长度可以事先给定,例如20次虚页访问)可以由程序随机产生,也可以事先保存在文件中。要求程序运行时屏幕能显示出置换过程中的状态信息并输出访问结束时的页面命中率。程序应允许通过为该进程分配不同的实页数,来比较两种置换算法的稳定性。四、实验说明 1.设计中虚页和实页的表示本设计利用C语言的结构体来描述虚页和实页的结构。pnpfntimepnpfnnext 虚页结构 实页结构在虚页结构中,pn代表虚页号,因为共10个虚页,所以pn的取值范围是0—9。pfn代表实页号,当一虚页未装入实页时,此项值为-1;当该虚页已装入某一实页时,此项值为所装入的实页的实页号pfn。time项在FIFO算法中不使用,在LRU中用来存放对该虚页的最近访问时间。在实页结构中,pn代表虚页号,表示pn所代表的虚页目前正放在此实页中。pfn代表实页号,取值范围(0—n-1)由动态指派的实页数n所决定。next是一个指向实页结构体的指针,用于多个实页以链表形式组织起来,关于实页链表的组织详见下面第4点。2.关于缺页次数的统计为计算命中率,需要统计在20次的虚页访问中命中的次数。为此,程序应设置一个计数器count,来统计虚页命中发生的次数。每当所访问的虚页的pfn项值不为-1,表示此虚页已被装入某实页内,此虚页被命中,count加1。最终命中率=count/20*100%。3.LRU算法中“最近最久未用”页面的确定为了能找到“最近最久未用”的虚页面,程序中可引入一个时间计数器countime,每当要访问一个虚页面时,countime的值加1,然后将所要访问的虚页的time项值设置为增值后的当前countime值,表示该虚页的最后一次被访问时间。当LRU算法需要置换时,从所有已分配实页的虚页中找出time值为最小的虚页就是“最近最久未用”的虚页面,应该将它置换出去。4.算法中实页的组织因为能分配的实页数n是在程序运行时由用户动态指派的,所以应使用链表组织动态产生的多个实页。为了调度算法实现的方便,可以考虑引入free和busy两个链表:free链表用于组织未分配出去的实页,首指针为free_head,初始时n个实页都处于free链表中;busy链表用于组织已分配出去的实页,首指针为busy_head,尾指针为busy_tail,初始值都为null。当所要访问的一个虚页不在实页中时,将产生缺页中断。此时若free链表不为空,就取下链表首指针所指的实页,并分配给该虚页。若free链表为空,则说明n个实页已全部分配出去,此时应进行页面置换:对于FIFO算法要将busy_head 所指的实页从busy链表中取下,分配给该虚页,然后再将该实页插入到busy链表尾部;对于LRU算法则要从所有已分配实页的虚页中找出time值为最小的虚页,将该虚页从装载它的那个实页中置换出去,并在该实页中装入当前正要访问的虚页。~
(1)通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成: ①、 50%的指令是顺序执行的; ②、 25%的指令是均匀分布在前地址部分; ③、 25%的指令是均匀分布在后地址部分。 具体的实施方法是: ① 在[0,319]的指令地址之间随机选取一起点m; ② 顺序 执行一条指令,即执行地址为m+1的指令; ③ 在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’; ④ 顺序执行一条指令,其地址为m’+1; ⑤ 在后地址[m’+2,319]中随机选取一条指令并执行; ⑥ 重复上述步骤,直至执行320次指令。 (2) 将指令序列变换成页地址流 设:①页面大小为1K; ②用户内存容量为4页到32页; ③用户虚存容量为32K; 在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为: 第0条~第9条指令为第0页(对应的虚存地址为[0,9]); 第10条~第19条指令为第1页(对应的虚存地址为[10,19]); . 第310条~第319条指令为第31页(对应的虚存地址为[310,319]); 按以上方式,用户指令可组成32页。 (3) 计算并输出下述各种算法在不同的内存容量下的命中率。 ① 先进先出的算法(FIFO); ② 最近最少使用算法(LRR); ③ 最佳淘汰法(OPT):先淘汰最不常用的页地址; ④ 最少访问页面算法(LFR); ⑤ 最近不经常使用算法(NUR)。 其中③和④为选择内容。 命中率=1-(页面失效次数)/(页地址流长度) 在本实验中,页地址流的长度为320,页面失效次数为每次访问相应指令时,该指令所对应的页不在内存的次数。
、实验内容与要求 1、熟悉windows的编程接口,使用系统调用编程实现将参数1对应文件1.txt和参数2对应文件2.txt的内容合并到参数3对应文件zong.txt中(上传文件名为学号后5位ex0701.c)。 2、使用windows提供的命令将文件1.txt和文件2.txt的内容合并到文件total.txt中 (请将实现的操作命令写入下题批处理文件的第一行)。 3、主管助理小张经常接收公司员工发来的文件,开始为了节省时间,小张将下载的文件都保存在文件夹xiazai中(文件名如图1所示,下载后直接解压即可),这样不便于后期的统计和分类管理,现在领导要求必须为所有员工(90人)每人单独建立一个文件夹(以员工工号命名10201、10202......10290),然后将他们提交的文件分别剪切到各自对应的文件夹中(如图2所示)。于是小张开始为7名员工建立文件夹,再一个一个的去做……同学们想想有没有一种方法能快速完成所要求的操作呢? 请熟悉windows的命令接口,使用windows提供的常用命令copy、md、del等编写一个批处理文件(上传文件名为学号后5位ex0703.bat),实现所要求的功能: 1、启动linux系统或通过windows telnet到linux。 2、用huas用户名和密码123456登入系统中。 3、打开一终端窗口(在linux桌面上单击右键,选择从终端打开)。然后在其中输入以下命令实验。 4、熟悉常用操作命令. 5、编辑如下源代码(实验教材P86 1.进程的创建)并保存 二、实验目的 (1)加深对进程概念的理解,明确进程和程序的区别。 (2)分析进程竞争资源现象,学习解决进程互斥的方法。 (3了解Linux系统中进程通信的基本原理。 、实验内容与要求 (1)任务一:编写一段程序,使其实现进程的软中断通信。 要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按DEL键);当捕捉到中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止: Child Processll is Killed by Parent! Child Processl2 is Killed by Parent! 父进程等待两个子进程终止后,输出如下的信息后终止 Parent Process is Killed! (2)任务二:在上面的程序中增加语句signal (SIGNAL, SIG-IGN)和signal (SIGQUIT, SIG-IGN),观察执行结果,并分析原因。 (3)任务:进程的管道通信 编制一段程序,实现进程的管道通信。 使用系统调用pipe()建立一条管道线;两个子进程P1和P2分别向管道中写一句话: Child 1 is sending a message! Child 2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。 要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。 二、实验目的 自行编制模拟程序,通过形象化的状态显示,加深理解进程的概念、进程之间的状态转换及其所带来的PCB内容 、组织的变化,理解进程与其PCB间的一一对应关系。 、实验内容与要求 1)设计并实现一个模拟进程状态转换及其相应PCB内容、组织结构变化的程序。 2)独立编写、调试程序。进程的数目、进程的状态模型(状态、五状态、七状态或其它)以及PCB的组织形式可自行选择。 3)合理设计与进程PCB相对应的数据结构。PCB的内容要涵盖进程的基本信息、控制信息、资源需求及现场信息。 4)设计出可视性较好的界面,应能反映出进程状态的变化引起的对应PCB内容、组织结构的变化。 二、实验目的 存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常用的虚拟存储管理技术。本实验的目的是通过请求页式管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。 、实验内容与要求 通过计算不同算法的命中率比较算法的优劣。同时也考虑了用户内存容量对命中率的影响。页面失效次数为每次访问相应指令时,该指令所对应的页不在内存中的次数。 计算并输出下属算法在不同内存容量下的命中率。  先进先出的算法(FIFO); 最近最少使用算法(LRU) 二、实验目的 死锁会引起计算机工作僵死,因此操作系统中必须防止。本实验的目的在于使用高级语言编写和调试一个系统动态分配资源的简单模拟程序,了解死锁产生的条件和原因,并采用银行家算法有效地防止死锁的发生,以加深对课堂上所讲授的知识的理解。 、实验内容与要求 设计有n个进程共享m个系统资源的系统,进程可动态的申请和释放资源,系统按各进程的申请动态的分配资源。 系统能显示各个进程申请和释放资源,以及系统动态分配资源的过程,便于用户观察和分析。 四、算法描述(含数据结构定义)或流程图 (一) 数据结构 1. 可利用资源向量Available ,它是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源的数目,其初始值是系统中所配置的该类全部可用资源数目。其数值随该类资源的分配和回收而动态地改变。如果Available(j)=k,标是系统中现有Rj类资源k个。 2. 最大需求矩阵Max,这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max(i,j)=k,表示进程i需要Rj类资源的最大数目为k。 3. 分配矩阵Allocation,这是一个n×m的矩阵,它定义了系统中的每类资源当前一分配到每一个进程的资源数。如果Allocation(i,j)=k,表示进程i当前已经分到Rj类资源的数目为k。Allocation i表示进程i的分配向量,有矩阵Allocation的第i行构成。 4. 需求矩阵Need,这是一个n×m的矩阵,用以表示每个进程还需要的各类资源的数目。如果Need(i,j)=k,表示进程i还需要Rj类资源k个,才能完成其任务。Need i表示进程i的需求向量,由矩阵Need的第i行构成。 上述个矩阵间存在关系:Need(i,j)=Max(i,j)-Allocation(i,j)。 (二) 银行家算法 Request i 是进程Pi 的请求向量。Request i (j)=k表示进程Pi请求分配Rj类资源k个。当Pi发出资源请求后,系统按下述步骤进行检查: 1. 如果Request i ≤Need,则转向步骤2;否则,认为出错,因为它所请求的资源数已超过它当前的最大需求量。 2. 如果Request i ≤Available,则转向步骤3;否则,表示系统中尚无足够的资源满足Pi的申请,Pi必须等待。 3. 系统试探性地把资源分配给进程Pi,并修改下面数据结构中的数值: 二、实验目的 磁盘是高速、大容量、旋转型、可直接存取的存储设备。它作为计算机系统的辅助存储器,担负着繁重的输入输出工作,在现代计算机系统中往往同时会有若干个要求访问磁盘的输入输出要求。系统可采用一种策略,尽可能按最佳次序执行访问磁盘的请求。由于磁盘访问时间主要受寻道时间T的影响,为此需要采用合适的寻道算法,以降低寻道时间。本实验要求模拟设计一个磁盘调度程序,观察调度程序的动态运行过程。通过实验来理解和掌握磁盘调度的职能。 、实验内容与要求 分别模拟如下磁盘调度算法,对磁盘进行移臂操作:  先来先服务算法  最短寻道优先算法 1. 假设磁盘只有一个盘面,并且磁盘是可移动头磁盘。 2. 磁盘是可供多个进程共享的存储设备,但一个磁盘每个时刻只能为一个进程服务。当有进程在访问某个磁盘时,其它想访问该磁盘的进程必须等待,直到磁盘一次工作结束。当有多个进程提出输入输出请求而处于等待状态时,可用磁盘调度算法从若干个等待访问者中选择一个进程,让它访问磁盘。为此设置“驱动调度”进程。 3. 由于磁盘与处理器是并行工作的,所以当磁盘在为一个进程服务时,占有处理器的其它进程可以提出使用磁盘(这里我们只要求访问磁道),即动态申请访问磁道,为此设置“接受请求”进程。 4. 为了模拟以上两个进程的执行,可以考虑使用随机数来确定二者的允许顺序,参考程序流程图。 5. “接受请求”进程建立一张“进程请求I/O”表,指出等待访问磁盘的进程要求访问的磁道,表的格式如下: 进程名 要求访问的磁道号 6. 磁盘调度的功能是查“请求I/O”表,当有等待访问的进程时,按磁盘调度算法从中选择一个等待访问的进程,按其指定的要求访问磁道。流程图中的“初始化”工作包括:初始化“请求I/O”表,设置当前移臂方向;当前磁道号。并且假设程序运行前“请求I/O”表中已有若干进程(4~8个)申请访问相应磁道。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值