欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    操作系统实验报告——进程调度(共21页).docx

    • 资源ID:14049143       资源大小:859.84KB        全文页数:21页
    • 资源格式: DOCX        下载积分:20金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要20金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    操作系统实验报告——进程调度(共21页).docx

    精选优质文档-倾情为你奉上北京邮电大学软件学院2019-2020学年第2学期实验报告 课程名称: 操作系统 实验名称: 进程调度 实验完成人: 日 期: 2019 年 11 月 26 日一、 实验目的1. 理解 Linux 管理进程所用到的数据结构。 2. 理解 Linux 的进程调度算法的处理逻辑及其实现所用到的数据结构。二、 实验内容1. 通过查阅参考书或者上网找资料,熟悉/usr/src/linux(注意:这里最后一级目录名 可能是个含有具体内核版本号和“linux”字符串的名字)下各子目录的内容,即所含 Linux 源代码的情况。 2. 分析 Linux 进程调度有关函数的源代码,主要是 schedule()函数,并且要对它们 引用的头文件等一并分析。 3. 实现 Linux 的进程调度算法及理解其实现所用的主要数据结构。三、 实验环境Linux下使用gcc+vscode四、 实验过程描述第一部分:源代码分析:所需头文件:#include <linux/sched.h>#include <linux/kernel.h>#include <linux/sys.h>#include <linux/fdreg.h>#include <asm/system.h>#include <asm/io.h>#include <asm/segment.h>#include <signal.h><linux/kernel.h>:内核头文件,含有一些内核常用函数的原形定义。<linux/fdreg.h>:软驱头文件,含有软盘控制器参数的一些定义。<linux/sched.h>:调度程序头文件,主要定义了任务结构task_struct、初始任务0的数据,以及一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。<linux/sys.h>:系统调用头文件,主要是系统调用C函数处理程序。 <asm/io.h>:I/O头文件,以宏的嵌入汇编程序形式定义对I/O端口操作的函数。<asm/segment.h>:段操作头文件,定义了有关段寄存器操作的嵌入式汇编函数。<asm/system.h>:系统头文件,定义了设置或修改描述符/中断门等的嵌入式汇编宏。<signal.h>:信号头文件,定义信号符号常量,信号结构以及信号操作函数原型。Schedule.c部分函数分析:(大多写在注释里)show_task()函数某个进程的状态信息以及空间大小void show_task(int nr,struct task_struct * p)/显示p指向的nr号进程的相关信息    int i,j = 4096-sizeof(struct task_struct);/j记录了任务结构体之后的堆栈空间大小    printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);/打印进程的各种信息    i=0;    while (i<j && !(char *)(p+1)i)/计算了任务之后空字节的大小        i+;    printk("%d/%d chars free in kernel stacknr",i,j);/内核栈最大为j,空字节数是i,比例i/j   void show_stat(void)/打印所有进程的状态信息    int i;    for (i=0;i<NR_TASKS;i+)        if (taski)            show_task(i,taski);Schedule()分析:schedule函数首先对所有的任务检查,唤醒任何一个已经得到信号的任务,也就是针对任务数组中的每个任务,检查其警报定时值alarm。如果任务的alarm已经超期(alarm < jiffies),则在它的信号位图中设置SIGALARM,然后清除alarm值。之后schedule()函数首先扫描任务队列,通过比较每个就绪状态任务的运行时间递减计数counter的值来确定当前哪个进程运行的时间最少,哪个counter值最大.counter越大就说明运行时间越短,于是就选中该进程,并使用任务切换宏函数到该进程运行利用switch_to函数完成任务转换。如果所有的就绪任务的该值都是0,则表示此刻所有任务的时间片都已运行完。于是就根据任务的优先权值priority,重置每个任务的运行时间counter。 void schedule(void)    int i, next, c;    struct task_struct *p;    /* check alarm, wake up any interruptible tasks that have got a signal */    for (p = &LAST_TASK; p > &FIRST_TASK; -p) /把p初始化为指向最后一个进程的地址的指针,逆向扫描所有进程        if (*p)         /当前进程            if (*p)->timeout && (*p)->timeout < jiffies)             / jiffies是持续变的,timeout 是阈值                (*p)->timeout = 0;                /如果当前进程等待很久了,并且这个进程处于TASK_INTERRUPTIBLE                if (*p)->state = TASK_INTERRUPTIBLE)                     (*p)->state = TASK_RUNNING; /我们就把这个进程置与TASK_RUNNING状态                        if (*p)->alarm && (*p)->alarm < jiffies)             /如果此时jiffies大于alarm信号周期,则让将SIGALRM写入进程的信号位                (*p)->signal |= (1 << (SIGALRM - 1);                (*p)->alarm = 0;                        if (*p)->signal & (_BLOCKABLE & (*p)->blocked) &&                (*p)->state = TASK_INTERRUPTIBLE) / 除SIGKILL SIGSTOP信号外,其他信号都是非阻塞状态的话,并且进程处于TASK_INTERRUPTIBLE                (*p)->state = TASK_RUNNING; /把这个进程置与TASK_RUNNING状态            /* this is the scheduler proper: */    while (1)           c = -1;        next = 0;        i = NR_TASKS;        p = &taskNR_TASKS;        while (-i)         /把所有进程都扫一遍,counter是递减的,找出counter最大的进程,保存在next里面            if (!*-p) /当前*p指向进程为空,下一个                continue;            if (*p)->state = TASK_RUNNING && (*p)->counter > c)                /counter是任务运行时间计数,如果当前进程是执行状态且运行时间数大于c                 c = (*p)->counter, next = i;                if (c)            break; /c>0 就说明找到了已经运行一段时间,并且运行时间最短的进程,跳出while(1)        for (p = &LAST_TASK; p > &FIRST_TASK; -p) /如果c=0,说明所有schedule的进程都没有运行            if (*p)               (*p)->counter = (*p)->counter >> 1) +                                (*p)->priority; /重新计算counter = counter/2 + priority        switch_to(next); /让进程next使用CPUSleep_on()函数分析:Sleep_on()函数 sleep_on()函数的主要功能是当一个进程(或任务)所请求的资源正等待资源响应或不在内存中时暂时切换出去,放在等待队列中等待一段时间,先让别的程序运行一段时间,当切换回来后再继续运行。巧妙的利用了tmp指针来作为与等待队列的联系void sleep_on(struct task_struct *p)    struct task_struct *tmp;    if (!p)        return;    if (current = &(init_task.task)          panic("task0 trying to sleep");    tmp = *p; / tmp 指向原等待队列的头指针    *p = current; /*p 指向等待队列的头指针,把current放入等待队列current->state = TASK_INTERRUPTIBLE; /当前状态为不可中断    schedule();/调度一下,    if (tmp)        tmp->state = 0;/task_runningWake_up()函数分析:Wake_up用来唤醒进程(将状态置为task_running即可)void wake_up(struct task_struct *p)/唤醒进程    if (p && *p)         if (*p).state = TASK_STOPPED)            printk("wake_up: TASK_STOPPED");        if (*p).state = TASK_ZOMBIE)            printk("wake_up: TASK_ZOMBIE");        (*p).state=0; /TASK_RUNNING    第二部分:实现进程调度算法进程调度算法:操作系统通过PCB来控制进程。PCB是进程实体的一部分,是操作系统中最重要的记录性数据结构,用来管理和控制进程,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。为了模拟进程调度算法,自定义了PCB:typedef struct PCB    _pid_t pid;    int priority;    int round_time;    int wait_time;    int demand_time;    /所需要的总时间    int cmplt_time;     /完成时间    int remain_time;    /还需要的时间(RR)    int suspend_time;   /暂时被挂起的时刻(RR)    int arrive_time;    /到达时间    int start_time;     /开始执行时间    struct PCB* next;*p_pcb,PCB;然后实现FCFS,SJF,RR算法:FCFS算法:先给进程队列排序,按时间的先后顺序来排,先来的排前面。排好序后可以计算出每个进程的开始执行时间和结束时间void FCFS(p_pcb head)    insertionSortList(head, fcfs); /按到达时间排序    p_pcb p = head;    head->cmplt_time = head->demand_time;    head->round_time = head->demand_time;    head->wait_time = 0;        /初始化头节点    while (p->next)            if (p->next->arrive_time < p->cmplt_time) /当前到达时间在上一个作业结束时间之前                    p->next->start_time = p->cmplt_time; /上一个任务完成时下一个任务开始                else /当前到达时间在上一个作业结束时间之后                    p->next->start_time = p->next->arrive_time;     /开始时间及到达时间                p->next->wait_time = p->next->start_time - p->next->arrive_time;   /等待时间=开始时间-到达时间        p->next->cmplt_time = p->next->start_time + p->next->demand_time; /完成时间=开始时间+服务时间        p->next->round_time = p->next->wait_time + p->next->demand_time;  /周转时间=等待时间+执行时间        p = p->next;        visit(head);        /打印结果SJF算法:假设所有进程在时间0时到达,则先给所有程序按所需执行时间排序,然后依次执行,计算出开始时间和结束时间。void SJF(p_pcb head) /假设所有进程在同一时刻到达    insertionSortList(head, sjf);    p_pcb p = head;    head->arrive_time = 0;    head->cmplt_time = head->demand_time;    head->round_time = head->demand_time;    head->wait_time = 0;        /初始化头节点    while (p->next)            p->next->arrive_time = 0;        p->next->start_time = p->cmplt_time; /上一个任务完成时下一个任务开始        p->next->wait_time = p->next->start_time - p->next->arrive_time;    /等待时间=开始时间-到达时间        p->next->cmplt_time = p->next->start_time + p->next->demand_time; /完成时间=上一个完成时间+服务时间        p->next->round_time = p->next->wait_time + p->next->demand_time;  /周转时间=完成时间-到达时间        p = p->next;        visit(head);RR:时间片轮转。假设所有程序在时间0时到达,然后每个程序轮流用时间片来执行。利用循环链表来操作,轮到该程序(该pcb的节点)执行时给该节点的剩余时间remain-time减时间片时间,如果剩余时间为0就将其移除循环链表,然后指向下一个节点。最后依次轮回,直到循环链表中只剩下一个节点。void RR(p_pcb head)    float quantum = 5.0;    p_pcb p = head;    while (p->next)     /预处理,初始化remain-time            p->start_time = 0;        p->remain_time = p->demand_time;        p = p->next;        p->start_time = 0; /处理最后一个节点    p->remain_time = p->demand_time;    printf("pid %d,star at %d,remain %dn", p->pid, p->start_time, p->remain_time);    p->next = head; /初始化为循环链表,方便后续操作    /从头开始    p = head;    int i = 0;          /记录经过了多少时间片    while (p->next != p)            if (p->next->remain_time > quantum)     /还需要的时间大于时间片时间                    p->next->start_time = i * quantum;      /开始时间为时间片开始时间            p->next->suspend_time = p->next->start_time + quantum;      /暂停时间为开始时间+时间片时间            p->next->remain_time -= quantum;            /还需要的时间自减            printf("process %d start at time %d with time quantum %.2f,and %d leftn", p->next->pid, p->next->start_time, quantum, p->next->remain_time);                else                                /在改时间片内可以完成此任务                    p->next->cmplt_time = p->next->start_time + p->next->remain_time;   /开始时间+所需时间            printf("process %d start at %dn", p->next->pid, p->next->start_time);            printf("process %d complete at %dn", p->next->pid, p->next->cmplt_time);            delete (p); /删除p->next                i+;        p = p->next;    还用到的算法:插入排序void insertionSortList(p_pcb head, Type type)       /插入排序    if (head = NULL | head->next = NULL)        return;    p_pcb p = head->next, pstart = (p_pcb)malloc(sizeof(PCB), pend = head;    pstart->next = head; /为了操作方便,添加一个头结点    while (p)            p_pcb tmp = pstart->next, pre = pstart;        if (type = fcfs)                    while (tmp != p && p->arrive_time >= tmp->arrive_time) /找到插入位置                            tmp = tmp->next;                pre = pre->next;                            else if (type = sjf)                    while (tmp != p && p->demand_time >= tmp->demand_time) /找到插入位置                            tmp = tmp->next;                pre = pre->next;                            if (tmp = p)            pend = p;        else                    pend->next = p->next;            p->next = tmp;            pre->next = p;                p = pend->next;            head = pstart->next;        free(pstart);五、 实验结果模拟了FCFS算法,SJF算法以及RR算法(代码见后面)。FCFS算法:先来先执行,根据到达时间对执行顺序行排序:SJF:短任务执行:时间片为2时的RR:时间片为5时的RR:六、 附件6.1 附件1:源代码Pcb.h#include "unistd.h"typedef enum Type    fcfs=1,sjf=2Type;typedef struct PCB    _pid_t pid;    int priority;    int round_time;    int wait_time;    int demand_time;    /所需要的总时间    int cmplt_time;     /完成时间    int remain_time;    /还需要的时间(RR)    int suspend_time;   /暂时被挂起的时刻(RR)    int arrive_time;    /到达时间    int start_time;     /开始执行时间    struct PCB* next;*p_pcb,PCB;void visit(p_pcb);void FCFS(p_pcb);void SJF(p_pcb);void RR(p_pcb);void initial(p_pcb);void destroy(p_pcb);void insertionSortList(p_pcb head,Type type);scheduling.c#include "pcb.h"#include "stdlib.h"#include <stdio.h>#include<time.h>void initial(p_pcb queue)       /初始化节点    queue->arrive_time = 0;    queue->demand_time = 0;    queue->next = NULL;void destroy(p_pcb head)        /销毁链表     p_pcb p = head;    while (p)            p_pcb temp = p;        p = p->next;        free(temp);    void add(p_pcb head, p_pcb new)     /添加节点    p_pcb p = head;    while (p->next)        p = p->next;    p->next = new;    new->next = NULL;void delete (p_pcb p) /删除p之后的节点    p_pcb temp = p->next;    p->next = p->next->next;    free(temp);void insertionSortList(p_pcb head, Type type)       /插入排序    if (head = NULL | head->next = NULL)        return;    p_pcb p = head->next, pstart = (p_pcb)malloc(sizeof(PCB), pend = head;    pstart->next = head; /为了操作方便,添加一个头结点    while (p)            p_pcb tmp = pstart->next, pre = pstart;        if (type = fcfs)                    while (tmp != p && p->arrive_time >= tmp->arrive_time) /找到插入位置                            tmp = tmp->next;                pre = pre->next;                            else if (type = sjf)                    while (tmp != p && p->demand_time >= tmp->demand_time) /找到插入位置                            tmp = tmp->next;                pre = pre->next;                            if (tmp = p)            pend = p;        else                    pend->next = p->next;            p->next = tmp;            pre->next = p;                p = pend->next;            head = pstart->next;        free(pstart);void FCFS(p_pcb head)    insertionSortList(head, fcfs); /按到达时间排序    p_pcb p = head;    head->cmplt_time = head->demand_time;    head->round_time = head->demand_time;    head->wait_time = 0;        /初始化头节点    while (p->next)            if (p->next->arrive_time < p->cmplt_time) /当前到达时间在上一个作业结束时间之前                    p->next->start_time = p->cmplt_time; /上一个任务完成时下一个任务开始                else /当前到达时间在上一个作业结束时间之后                    p->next->start_time = p->next->arrive_time;     /开始时间及到达时间                p->next->wait_time = p->next->start_time - p->next->arrive_time;   /等待时间=开始时间-到达时间        p->next->cmplt_time = p->next->start_time + p->next->demand_time; /完成时间=开始时间+服务时间        p->next->round_time = p->next->wait_time + p->next->demand_time;  /周转时间=等待时间+执行时间        p = p->next;        visit(head);        /打印结果void SJF(p_pcb head) /假设所有进程在同一时刻到达    insertionSortList(head, sjf);    p_pcb p = head;    head->arrive_time = 0;    head->cmplt_time = head->demand_time;    head->round_time = head->demand_time;    head->wait_time = 0;        /初始化头节点    while (p->next)            p->next->arrive_time = 0;        p->next->start_time = p->cmplt_time; /上一个任务完成时下一个任务开始        p->next->wait_time = p->next->start_time - p->next->arrive_time;    /等待时间=开始时间-到达时间        p->next->cmplt_time = p->next->start_time + p->next->demand_time; /完成时间=上一个完成时间+服务时间        p->next->round_time = p->next->wait_time + p->next->demand_time;  /周转时间=完成时间-到达时间        p = p->next;        visit(head);void RR(p_pcb head)    float quantum = 5.0;    p_pcb p = head;    while (p->next)     /预处理,初始化remain-time            p->start_time = 0;        p->remain_time = p->demand_time;        p = p->next;        p->start_time = 0; /处理最后一个节点    p->remain_time = p->demand_time;    printf("pid %d,star at %d,remain %dn", p->pid, p->start_time, p->remain_time);    p->next = head; /初始化为循环链表,方便后续操作    /从头开始    p = head;    int i = 0;          /记录经过了多少时间片    while (p->next != p)            if (p->next->remain_time > quantum)     /还需要的时间大于时间片时间                    p->next->start_time = i * quantum;      /开始时间为时间片开始时间            p->next->suspend_time = p->next->start_time + quantum;      /暂停时间为开始时间+时间片时间            p->next->remain_time -= quantum;            /还需要的时间自减            printf("process %d start at time %d with time quantum %.2f,and %d leftn", p->next->pid, p->next->start_time, quantum, p->next->remain_time);                else                                /在改时间片内可以完成此任务                    p->next->cmplt_time = p->next->start_time + p->next->remain_time;   /开始时间+所需时间            printf("pro

    注意事项

    本文(操作系统实验报告——进程调度(共21页).docx)为本站会员(飞****2)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开