头歌操作系统实训总结

目录

死锁

实验一:LINUX环境体验

第一关 LINUX环境目录

第二关:Linux文件操作命令

第三关Linux权限管理

Linux系统的进程控制

第1关:进程创建

第2关:进程加载

第3关:进程等待与退出

生产者消费者问题实践

第1关:生产者消费者问题实践

处理机调度

第1关:先来先服务调度算法

第2关:短作业优先调度算法

第3关:高相应比优先调度算法

动态分区算法

第2关:最佳适应算法


死锁

  • 1、系统出现死锁时一定同时保持了四个必要条件,对资源采用按序分配算法后可破坏的条件是(A)。

    A、循环等待条件
    B、互斥条件
    C、占有并等待条件
    D、不可抢占条件
  • 2、资源的静态分配算法在解决死锁问题中是用于(B)。

    A、避免死锁
    B、预防死锁
    C、检测死锁
    D、解除死锁
  • 3、产生系统死锁的原因可能是由于(A)。

    A、多个进程竞争资源出现了循环等待
    B、进程释放资源
    C、一个进程进入死循环
    D、多个进程竞争共享型设备
  • 4、为了避免系统可能出现死锁,分配资源可以采用的算法是(D)。

    A、抢占式分配
    B、按序分配
    C、静态分配
    D、银行家算法
  • 5、某系统采用了银行家算法,则下列说法正确的是(C)。

    A、系统处于安全状态时一定会发生死锁
    B、系统处于安全状态时可能会发生死锁
    C、系统处于不安全状态时可能会发生死锁
    D、系统处于不安全状态时一定会发生死锁
  • 6、银行家算法中的数据结构包括可用资源向量Available、最大需求矩阵Max、分配矩阵Allocation、需求矩阵Need,下列选项中表述正确的是(B)。

    A、Max[i,j]=Available[i,j]+Need[i,j]
    B、Need[i,j]=Max[i,j]-Allocation[i,j]
    C、Max[i,j]=Allocation[i,j]-Need[i,j]
    D、Allocation[i,j]=Need[i,j]+Max[i,j]
  • 7、下列选项中,属于检测死锁的方法是(A)。

    A、资源分配图简化法
    B、银行家算法
    C、撤销进程法
    D、资源静态分配法
  • 8、下列选项中,属于解除死锁的方法是(B)。

    A、资源分配图简化法
    B、剥夺资源法
    C、银行家算法
    D、资源静态分配法
  • 9、产生死锁的必要条件有(ABCD)。

    A、循环等待
    B、互斥
    C、占有并等待
    D、非抢占
  • 10、用银行家算法避免死锁时,检测到(D)时才分配资源。

    A、进程已占用的资源数与本次申请的资源数之和不超过对资源的最大需求量,且现存资源能满足尚需的最大资源量 
    B、进程己占用的资源数与本次申请资源数之和超过对资源的最大需求量
    C、进程首次申请资源时对资源的最大需求量超过系统现存的资源量 
    D、进程已占用的资源数与本次申请的资源数之和不超过对资源的最大需求量,且现存资源能满足本次申请量,并且本次分配后系统不会死锁

实验一:LINUX环境体验

第一关 LINUX环境目录

启动环境、打开终端

(1)在根目录下创建一个文件夹命名为linux

mkdir linux

(2)在根目录下创建一个文件命名为hello.txt

touch hello.txt

(3)将文件复制到linux文件夹下,并且改名为1.txt

cp hello.txt linux/1.txt

(4)删除根目录下的hello.txt

rm hello.txt

第二关:Linux文件操作命令

cd /home/headless
vi test.txt

输入:

Hello,Linux!

按ESC,再按 :wq

第三关Linux权限管理

切记按顺序一个一个来,如果过不了就重新启动环境

cd /root
touch oldFile1 oldFile2 oldFile3 oldFile4
chmod u+x oldFile1
chmod g-r oldFile2
chmod o+x oldFile3
chmod u=r,g=w,o=x oldFile4

Linux系统的进程控制

第1关:进程创建

通过提示,在右侧编辑器中补充代码,完成在指定文件中添加内容,具体要求如下:

  1. 创建进程;
  2. 父进程向文件中添加hello 和 world!
  3. 子进程向文件中添加hello 和 welcome!
  4. 只需修改文件内容即可,平台将为你输出文件内容。

提示:fork()函数的返回值为0时则为子进程。

#include 
#include 
#include 
#include 

int main(){
    
    FILE *fp = fopen("test.txt", "w+");
    int pid; //pid表示fork函数的返回值

    // 检查文件是否成功打开
    if (fp == NULL) {
        printf("File open error!\n");
        return 1;
    }

    pid = fork(); // 创建子进程

    if (pid < 0) {
        // fork失败
        printf("Fork failed!\n");
        return 1;
    } else if (pid == 0) {
        // 子进程
        fprintf(fp, "hello welcome!\n");
    } else {
        // 父进程
        fprintf(fp, "hello world!\n");
    }

    fclose(fp); // 关闭文件
    return 0;
}

第2关:进程加载

在右侧编辑器补充代码,要求如下:

  1. 创建进程;
  2. 在父进程中输出entering main process---
  3. 在子进程中使用execl()函数调用src/step2/hello.c文件,测试环境中已将path置为src/step2,因此带路径的文件名为./hello
#include 
#include
#include
 			//请在此处添加导入相应库函数代码
int main(){
	/**********  Begin  **********/
    
    
    //父进程输出
    int pid;
    pid=fork();
    if(pid==0)
    {
        execl("./hello",NULL);
    }
    else
    {
        printf("entering main process---\n");
    }    
    //子进程执行hello.c文件
     


	/**********  End  **********/
    return 0;
}

第3关:进程等待与退出

根据提示,在右侧编辑器补充代码,创建两个子进程,第一个进程打印I am first process!,第二个进程打印I am second process!,父进程打印I am father process!

要求实现先打印第一个进程内容,再打印第二个进程内容,最后打印父进程内容。

提示:进程加载execl函数调用输出用法execl("/bin/echo","echo", "输出语句", NULL);

#include
#include
#include
#include
					//请在此处添加导入相应库函数代码

int main()
{
	int p1, p2; //进程ID
  	/**********  Begin  **********/
    p1=fork();
    if(p1==0)
        execl("/bin/echo","echo", "I am first process!", NULL); 
    else 
        wait(NULL);
    p2=fork();
    if(p2==0)
        execl("/bin/echo","echo", "I am second process!", NULL); 
    else 
        wait(NULL);
    
    printf("I am father process!");
    //execl("/bin/echo","echo",NULL);
	/**********  End  **********/
	return 0;
}

生产者消费者问题实践

第1关:生产者消费者问题实践

void *Consumer()
{
    int nextc = 0;
    int i = 0;
    for (; i < 10; ++i)
    {
        sem_wait(&full);
        pthread_mutex_lock(&mutex);
        nextc = buffer[out];
        printf("Consume one message:%d\n", nextc);
        fflush(stdout);
        out = (out + 1) % SIZE;
        pthread_mutex_unlock(&mutex);
        sem_post(&empty);
    }
}

第二关生产者消费者问题实践


void *Son()
{
	//请添加儿子线程的函数代码
    while(1)
    {
int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒
		usleep(time * 100000);        
		sem_wait(&orange); 
        pthread_mutex_lock(&mutex);
		printf("儿子取了一个桔子\n") ;
        fflush(stdout);
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
 
    }
 
}

处理机调度

第1关:先来先服务调度算法

#include 
#include 
 
#define N 5
 
typedef struct JCB
{
	char name[10];
	int arriveTime;  //到达时间 
	int serveTime;   //服务时间 
	int finishTime;  //完成时间 
	int aroundTime;  //周转时间 
	float waroundTime; //带权周转时间 
}PCB;
 
 
 
void input(PCB pcb[N])
{
	strcpy(pcb[0].name,"A");
	pcb[0].arriveTime = 0;
	pcb[0].serveTime = 3;
	
	strcpy(pcb[1].name,"B");
	pcb[1].arriveTime = 2;
	pcb[1].serveTime = 6;
	
	strcpy(pcb[2].name,"C");
	pcb[2].arriveTime = 4;
	pcb[2].serveTime = 4;
	
	strcpy(pcb[3].name,"D");
	pcb[3].arriveTime = 6;
	pcb[3].serveTime = 5;
	
	strcpy(pcb[4].name,"E");
	pcb[4].arriveTime = 8;
	pcb[4].serveTime = 2;
	
	int i = 0;
	for(; i < N; ++i)
	{
		pcb[i].finishTime = 0;
		pcb[i].aroundTime = 0;
		pcb[i].waroundTime = 0;
	}
 
}
 
void output(PCB pcb[N])
{
	int i = 0;
	printf("进程\t");
	printf("完成时间\t");
	printf("周转时间\t");
	printf("带权周转时间\t\n");
	for(; i < N; ++i)
	{
		printf("%s\t",pcb[i].name);
		printf("%d\t\t",pcb[i].finishTime);
		printf("%d\t\t",pcb[i].aroundTime);
		printf("%f\t\t\n",pcb[i].waroundTime);
	}
}
 
//先来先服务调度算法 
void FCFS(PCB pcb[N])
{
	//请补充先来先服务算法的实现代码
    int finished=0;
    int curTime=0;
    while(finished0||pcb[i].arriveTime>curTime)
            {
                continue;
            }
            if(pcb[i].arriveTime

第2关:短作业优先调度算法

#include 
#include 
 
#define N 5
 
typedef struct JCB
{
	char name[10];
	int arriveTime;  //到达时间 
	int serveTime;   //服务时间 
	int finishTime;  //完成时间 
	int aroundTime;  //周转时间 
	float waroundTime; //带权周转时间 
}PCB;
 
 
 
void input(PCB pcb[N])
{
	strcpy(pcb[0].name,"A");
	pcb[0].arriveTime = 0;
	pcb[0].serveTime = 3;
	
	strcpy(pcb[1].name,"B");
	pcb[1].arriveTime = 2;
	pcb[1].serveTime = 6;
	
	strcpy(pcb[2].name,"C");
	pcb[2].arriveTime = 4;
	pcb[2].serveTime = 4;
	
	strcpy(pcb[3].name,"D");
	pcb[3].arriveTime = 6;
	pcb[3].serveTime = 5;
	
	strcpy(pcb[4].name,"E");
	pcb[4].arriveTime = 8;
	pcb[4].serveTime = 2;
	
	int i = 0;
	for(; i < N; ++i)
	{
		pcb[i].finishTime = 0;
		pcb[i].aroundTime = 0;
		pcb[i].waroundTime = 0;
	}
 
}
 
void output(PCB pcb[N])
{
	int i = 0;
	printf("进程\t");
	printf("完成时间\t");
	printf("周转时间\t");
	printf("带权周转时间\t\n");
	for(; i < N; ++i)
	{
		printf("%s\t",pcb[i].name);
		printf("%d\t\t",pcb[i].finishTime);
		printf("%d\t\t",pcb[i].aroundTime);
		printf("%f\t\t\n",pcb[i].waroundTime);
	}
}
 
 
//短作业优先调度算法 
void SJF(PCB pcb[N])
{
	for(int i=2;ipcb[j].serveTime)
       {
           PCB a=pcb[i];
           pcb[i]=pcb[j];
           pcb[j]=a;
       } 
    }
 double time=pcb[0].arriveTime;
 for(int i=0;ipcb[j].arriveTime)
       {
           PCB a=pcb[i];
           pcb[i]=pcb[j];
           pcb[j]=a;
       } 
    }
}
 
 
int main()
{
	PCB pcb[N];
	
	
	input(pcb);
	SJF(pcb);
	printf("短作业优先SJF:\n"); 
	output(pcb);
	printf("\n");
	
}

第3关:高相应比优先调度算法

#include 
#include 
 
#define N 5
 
typedef struct JCB
{
	char name[10];
	int arriveTime;  //到达时间 
	int serveTime;   //服务时间 
	int finishTime;  //完成时间 
	int aroundTime;  //周转时间 
	float waroundTime; //带权周转时间 
}PCB;
 
 
 
void input(PCB pcb[N])
{
	strcpy(pcb[0].name,"A");
	pcb[0].arriveTime = 0;
	pcb[0].serveTime = 3;
	
	strcpy(pcb[1].name,"B");
	pcb[1].arriveTime = 2;
	pcb[1].serveTime = 6;
	
	strcpy(pcb[2].name,"C");
	pcb[2].arriveTime = 4;
	pcb[2].serveTime = 4;
	
	strcpy(pcb[3].name,"D");
	pcb[3].arriveTime = 6;
	pcb[3].serveTime = 5;
	
	strcpy(pcb[4].name,"E");
	pcb[4].arriveTime = 8;
	pcb[4].serveTime = 2;
	
	int i = 0;
	for(; i < N; ++i)
	{
		pcb[i].finishTime = 0;
		pcb[i].aroundTime = 0;
		pcb[i].waroundTime = 0;
	}
 
}
 
void output(PCB pcb[N])
{
	int i = 0;
	printf("进程\t");
	printf("完成时间\t");
	printf("周转时间\t");
	printf("带权周转时间\t\n");
	for(; i < N; ++i)
	{
		printf("%s\t",pcb[i].name);
		printf("%d\t\t",pcb[i].finishTime);
		printf("%d\t\t",pcb[i].aroundTime);
		printf("%f\t\t\n",pcb[i].waroundTime);
	}
}
 
 
//高响应比优先调度算法 
void HRRN(PCB pcb[N])
{
    for(int i=3;ipcb[j].serveTime)
       {
           PCB a=pcb[i];
           pcb[i]=pcb[j];
           pcb[j]=a;
       } 
    }
 double time=pcb[0].arriveTime;
 for(int i=0;ipcb[j].arriveTime)
       {
           PCB a=pcb[i];
           pcb[i]=pcb[j];
           pcb[j]=a;
       } 
    }
}
 
 
int main()
{
	PCB pcb[N];
	
	input(pcb);
	HRRN(pcb);
	printf("高响应比优先HRRN:\n"); 
	output(pcb);
	
}

动态分区算法

第1关:首次适应算法

#include 
#include 
const int Max_length=55;//最大内存
struct areaNode//管理分区的结构体
{
    int ID;//分区号 
    int size;//分区大小 
    int address;//分区地址 
    int flag;//使用状态,0为未占用,1为已占用
};
typedef struct DuNode//双向链表结点
{
  struct areaNode data;//数据域 
  struct DuNode *prior;//指针域 
  struct DuNode *next;
}*DuLinkList;
DuLinkList m_head = new DuNode, m_last = new DuNode;//双向链表首尾指针
void init()//分区链表初始化
{
  m_head->prior = NULL;
  m_head->next = m_last;
  m_last->prior = m_head;
  m_last->next = NULL;
  m_head->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_head->next;//指向空闲区队列的首地址 
  printf("+++++++++++++++++++++++++++++++++++++++\n");
  while (p)
  {
    printf("分区号:");
 if (p->data.ID == 0)
   printf("FREE\n");
 else
   printf("%d\n",p->data.ID);
 printf("分区起始地址:%d\n",p->data.address);
 printf("分区大小:%d\n",p->data.size);
 printf("分区状态:");
 if (p->data.flag)
   printf("已被占用\n");
 else
   printf("空闲\n");
 printf("——————————————————\n");
 p = p->next;
  }
}
bool first_fit(int id,int m_size)//首次适应算法,id为作业号,m_size为作业大小 
{
     //请补充使用首次适应算法给作业分配内存的函数代码
    DuLinkList p = m_head;
    while(p != m_last) {
        DuLinkList n = p->next;
        if(!n->data.flag && n->data.size >= m_size) {
            DuLinkList t = new DuNode();
            t->data.ID = id;
            t->data.size = m_size;
            t->data.address = n->data.address;
            t->data.flag = 1;
            n->data.address += m_size;
            n->data.size -= m_size;
            t->prior = p;
            t->next = n;
            p->next = t;
            n->prior = t;
        }
        p = n;
    }
}
void recycle(int id)//回收内存,id为释放内存的作业号 
{
    DuLinkList p = m_head;
    while(p != m_last) {
        DuLinkList n = p->next;
        if(n->data.ID == id) {
            p->next = n->next;
            n->next->prior = p;
            n->next->data.address -= n->data.size;
            m_last->data.size += n->data.size;
            delete n;
            n = n->next;
        }
        if(n != m_last)
            n->next->data.address = n->data.address + n->data.size;
        p = n;
    }
}
int main()
{
 init();
    printf("首次适应算法:\n");
 first_fit(1,15);
 first_fit(2,30);
 recycle(1);
 first_fit(3,8);
 first_fit(4,6);
 recycle(2);
 show();
 DuNode *p = m_head;
 while(p != NULL)
 {
  DuNode *temp =  p;
  p = p->next;
  delete(temp);
  temp = NULL;
 }
 return 0;
}

第2关:最佳适应算法

#include 
#include 
const int Max_length=55;//最大内存
struct areaNode//管理分区的结构体
{
    int ID;//分区号 
    int size;//分区大小 
    int address;//分区地址 
    int flag;//使用状态,0为未占用,1为已占用
};
typedef struct DuNode//双向链表结点
{
  struct areaNode data;//数据域 
  struct DuNode *prior;//指针域 
  struct DuNode *next;
}*DuLinkList;
DuLinkList m_head = new DuNode, m_last = new DuNode;//双向链表首尾指针
void init()//分区链表初始化
{
    m_head->prior = NULL;
    m_head->next = m_last;
    m_last->prior = m_head;
    m_last->next = NULL;
    m_head->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_head->next;//指向空闲区队列的首地址 
  printf("+++++++++++++++++++++++++++++++++++++++\n");
  while (p)
  {
    printf("分区号:");
 if (p->data.ID == 0)
   printf("FREE\n");
 else
   printf("%d\n",p->data.ID);
 printf("分区起始地址:%d\n",p->data.address);
 printf("分区大小:%d\n",p->data.size);
 printf("分区状态:");
 if (p->data.flag)
   printf("已被占用\n");
 else
   printf("空闲\n");
 printf("——————————————————\n");
 p = p->next;
  }
}
bool best_fit(int id, int m_size)//最佳适应算法,其中需要查找最佳的存放位置
{
      //请补充使用最佳适应算法给作业分配内存的函数代码
    DuLinkList p = m_head;
    DuLinkList t = nullptr;
    while(p != m_last) {
        DuLinkList n = p->next;
        if(!n->data.flag && n->data.size >= m_size) {
            if(t == nullptr || t->data.size > n->data.size){
                t = n;
            }
        }
        p = n;
    }
    if(t == nullptr)
        return false;
    if(t->data.size == m_size) {
        t->data.flag = 1;
        t->data.ID = id;
    }
    else {
        DuLinkList t2 = new DuNode();
        t2->next = t;
        t2->prior = t->prior;
        t->prior->next = t2;
        t->prior = t2;
        t2->data.ID = id;
        t2->data.flag = 1;
        t2->data.address = t->data.address;
        t->data.address += m_size;
        t2->data.size = m_size;
        t->data.size -= m_size;
    }
    return true;
}
void recycle(int id)//回收内存,id为释放内存的作业号 
{
     //请补充回收作业内存的函数代码
    DuLinkList p = m_head;
    DuLinkList n = nullptr;
    while(p != m_last) {
        n = p->next;
        if(n->data.ID == id) {
            break;
        }
        p = n;
    }
    if(n == nullptr || n == m_last)
        return;
    n->data.flag = 0;
    n->data.ID = 0;
    DuLinkList np = n->prior;
    DuLinkList nn = n->next;
    if(np != m_head && np->data.flag == 0) {
        np->prior->next = n;
        n->prior = np->prior->next;
        n->data.address = np->data.address;
        n->data.size += np->data.size;
        delete np;
    }
    if((nn != nullptr || nn != m_last) && nn->data.flag == 0) {
        nn->next->prior = n;
        n->next = nn->next->prior;
        n->data.size += nn->data.size;
        delete nn;
    }
}
int main()
{
    init();
    //最佳适应算法
    printf("最佳适应算法:\n");
    init();
    best_fit(1,15);
    best_fit(2,30);
    recycle(1);
    best_fit(3,8);
    best_fit(4,6);
    recycle(2);
    show();
    DuNode *p = m_head;
    while(p != NULL)
    {
        DuNode *temp =  p;
         p = p->next;
        delete(temp);
        temp = NULL;
        }
    return 0;
}

你可能感兴趣的:(操作系统,头歌)