golang模拟动态高优先权优先调度算法

 

实验二  动态高优先权优先调度

实验内容

模拟实现动态高优先权优先(若数值越大优先权越高,每运行一个时间单位优先权-n,若数值越小优先权越高,没运行一个时间单位优先权+n),具体如下:

设置进程体:进程名,进程的到达时间,服务时间,初始优先权,进程状态(W——等待,R——运行,F——完成),进程间的链接指针

进程初始化:由用户输入进程名、服务时间、初始优先权进行初始化,同时,初始化进程的状态为W。

显示函数:在进程调度前、调度中和调度后进行显示。

排序函数:对就绪状态的进程按照优先权排序。优先权相同时进入等待队列时间早的进程在前。注意考虑到达时间

调度函数:每次从等待队列队首调度优先权最高的进程执行,状态变化。并在执行一个时间单位后优先权变化,服务时间变化,状态变化。当服务时间为0时,状态变为F。

删除函数:撤销状态为F的进程。

实验要求

1、  测试数据可以随即输入或从文件中读入。

2、  必须要考虑到进程的到达时间

3、  最终能够计算每一个进程的周转时间。

 

实验代码

1.txt

process1 1 5 2 W
process2 1 4 7 W
process3 1 8 3 W
process5 1 6 9 W
process4 1 15 6 W

 

main.go

package main

import (
    "bufio"
    "container/heap"
    "fmt"
    "os"
    "strconv"
    "strings"
    "time"
)

type Item struct {
    name       string
    priority   int
    index      int
    arrival    int
    service    int
    oldservice int
    state      string
}

type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {

    if pq[i].priority == pq[j].priority {
        return pq[i].service < pq[i].service
    }
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

//优先队列的Pop并不是用这个Pop,最后的元素并不是优先级最高的!
func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    item.index = -1
    *pq = old[0 : n-1]
    return item
}

func (pq *PriorityQueue) Top() *Item {
    item := heap.Pop(pq).(*Item)
    heap.Push(pq, item)
    return item
}

func (pq *PriorityQueue) update(item *Item, priority, service int, state string) {
    item.priority = priority
    item.service = service
    item.state = state
    heap.Fix(pq, item.index)
}

//创建优先队列
var pq = make(PriorityQueue, 0)

func main() {
    f, err := os.OpenFile("1.txt", os.O_RDONLY, 0777)
    if err != nil {
        fmt.Println("没有找到1.txt!")
        os.Exit(1)
    }
    fmt.Println("请输入每秒改变优先级n")
    n := 1
    fmt.Scan(&n)
    reader := bufio.NewReader(f)

    for i := 0; i < 5; i++ {
        //每次读取一行
        buf, _, _ := reader.ReadLine()
        sli := strings.Fields(string(buf))
        priint, _ := strconv.Atoi(sli[3])
        arrint, _ := strconv.Atoi(sli[1])
        serint, _ := strconv.Atoi(sli[2])
        //创建实例
        one := &Item{
            name:       sli[0],
            priority:   priint,
            index:      i,
            arrival:    arrint,
            service:    serint,
            oldservice: serint,
            state:      sli[4],
        }
        heap.Push(&pq, one)
    }
    //初始化堆
    heap.Init(&pq)
    fmt.Println("请输入第x秒后的状态:")
    x := 0
    fmt.Scan(&x)
    //执行, 初始总数n为5,x为循环次数

    num := 5
    for second := 1; second <= x; second++ {

        time.Sleep(time.Second)
        // pq[num] != heap.Pop(*pq)!!!

        //临时优先队列
        var tempq = make(PriorityQueue, 0)

        //遍历所有堆元素,仅pq[0]优先级最高!
        for i := 0; i < num; i++ {
            onepq := pq[i]

            if onepq.state == "F" {
                //添加到tempq
                tempq = append(tempq, onepq)
                continue
            }

            //服务时间不为0,就让其-1,state设为R
            if onepq.service != 0 {
                if i == 0 {
                    //优先级最高
                    onepq.priority = pq[i].priority - n
                    onepq.service = pq[i].service - 1
                    onepq.state = "R"
                } else {
                    //堆里其他元素
                    onepq.priority = pq[i].priority + n
                    onepq.state = "W"
                }
            } else {
                //service=0, state设为F
                onepq.state = "F"
            }

            //添加到tempq
            tempq = append(tempq, onepq)
        }

        //删除堆里所有元素
        for pq.Len() > 0 {
            heap.Pop(&pq)
        }

        //把所有元素加到堆里
        for _, v := range tempq {
            heap.Push(&pq, v)
        }

        //输出
        fmt.Printf("\n第%d秒的状态表示\n", second)
        fmt.Println("进程名  |  服务时间  |  目前优先级  |  进程状态  |  平均周转时间")

        //输出堆
        for i := 0; i < num; i++ {
            if pq[i].oldservice == pq[i].service {
                fmt.Printf("%v      %v            %v            %v              0\n", pq[i].name, pq[i].service, pq[i].priority, pq[i].state)
            } else {
                fmt.Printf("%v      %v            %v            %v              %v\n", pq[i].name, pq[i].service, pq[i].priority, pq[i].state, (second-pq[i].arrival)*1.0/(pq[i].oldservice-pq[i].service))
            }

        }
    }
}

/*
    使用了golang的container/heap包,需要手动实现less/len/swap/push/pop方法,这里也自定义了update和top方法,需要注意有以下几点:
    1. heap并不是按优先级排序的,所以不能用for遍历,仅pq[0]优先级最高
    2. 在遍历堆内所有节点时不能直接update,因为fix方法会重新构建堆,我这里使用的方式是用切片来保存堆中所有的元素,空堆后再一次性push
*/

 

 

实验截图

前4秒状态:

 

 

后2秒状态:

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)用C语言来实现对N个进程采用动态优先权优先算法的进程调度。 (2)每个用来标识进程进程控制块PCB用结构来描述,包括以下字段: •••• 进程标识数 ID。 •••• 进程优先数 PRIORITY,并规定优先数越大的进程,其优先权。 •••• 进程已占用的CPU时间CPUTIME。 •••• 进程还需占用的CPU时间ALLTIME。当进程运行完毕时,ALLTIME变为0。•••• 进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK个时间片后,将进入阻塞状态。 •••• 进程被阻塞的时间BLOCKTIME,表示已足赛的进程再等待BLOCKTIME个时间片后,将转换成就绪状态。 •••• 进程状态START。 •••• 队列指针NEXT,用来将PCB排成队列。 (3)优先数改变的原则: •••进程在就绪队列中呆一个时间片,优先数加1。 •••进程每运行一个时间片,优先数减3。 (4)假设在调度前,系统中有5个进程,它们的初始状态如下: ID 0 1 2 3 4 PRIORITY 9 38 30 29 0 CPUTIME 0 0 0 0 0 ALLTIME 3 3 6 3 4 STARTBLOCK 2 -1 -1 -1 -1 BLOCKTIME 3 0 0 0 0 STATE READY READY READY READY READY (5)为了清楚的观察各进程的调度过程,程序应将每个时间片内的情况显示出来,参照的具体格式如下: RUNNING PROG:i READY-QUEUE:->id1->id2 BLOCK-QUEUE:->id3->id4 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ID 0 1 2 3 4 PRIORITY P0 P1 P2 P3 P4 CUPTIME C0 C1 C2 C3 C4 ALLTIME A0 A1 A2 A3 A4 STARTBLOCK T0 T1 T2 T3 T4 BLOCKTIME B0 B1 B2 B3 B4 STATE S0 S1 S2 S3 S4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值