Python模拟进程调度

上一篇 / 下一篇  2014-02-23 23:58:08 / 个人分类:Python

__author__ = 'SHUHUA'
#-*- coding: UTF-8 -*-
import random
titlebar='id'.ljust(5)+'到达时间'.ljust(15)+'服务时间'.ljust(15)+'开始时间'.ljust(15)+'结束时间'.ljust(15)+'周转时间'.ljust(15)+'带权周转时间'.ljust(15)+'\n'
list=[]#进程PCB队列
lastid = -1#上次调度之后的最后一个元素的id
timestep = 1#时间片大小,默认是1
ID=0
LE=1   #时间片轮转法中,剩余服务时间的记录
ARRIVE=2  #到达时间
SERVER=3  #服务时间
START=4   #开始时间
End=5     #结束时间
ZZ=6      #周转时间
AVGZZ=7   #平均周转时间


def show_process():#打印
     global flist,titlebar
     strs=''
     for i in range(len(list)):
        strs += str(list[i][ID]).ljust(5)+str(list[i][ARRIVE]).ljust(15)+str(list[i][SERVER]).ljust(15)+ str(list[i][START]).ljust(15)+ str(list[i][End]).ljust(15)+str(list[i][ZZ]).ljust(15) +str(list[i][AVGZZ]).ljust(15)+'\n'
     v1.set(titlebar + strs)

def random_process():#随机生成进程队列
    global list,lastid
    lastid=-1#每次刷新都要使最后一个已调度的作业索引为-1
    del list[:] # 每次都清空列表
    for i in range(10):
        id=i
        arrive=i#不要改为随机数
        server=random.randint(1,101)
        new=[id,'',arrive,server,'','','','']
        list.insert(i,new)
    show_process()

import tkMessageBox
def add_process():#添加进程
    global list,lastid,timestep
    k = True
    if eat.get()=='' or est.get()==''or eat.get().isdigit()==False or est.get().isdigit()==False:
        tkMessageBox.showerror( message="请正确输入内容")
        k=False
    if ok:
        if len(list)>0 and list[lastid][START] !='':#说明前面已经进行过调度
            if int(eat.get()) < list[lastid][ARRIVE]:
                k=False
                tkMessageBox.showerror(  message="当前已经过调度", detail=u"请输入不小于 "+str(list[lastid][ARRIVE])+u' 的到达时间' )
    if ok:
        id = len(list)
        arrive=int(eat.get())
        server=int(est.get())
        if r.get()=='3':#时间片轮转法时
            if etime.get()==''or (etime.get().isdigit()==False):
                tkMessageBox.showerror(  message="请正确输入", detail=u"时间片大小(默认为1)" )
            else:
                timestep=int(etime.get())
                new=[id,'',arrive,server,'','','','']
                list.insert(id,new)
                show_process()
        else:#先来先服务 or 短进程优先时
            new=[id,'',arrive,server,'','','','']
            list.insert(id,new)
            show_process()

def fcfs():#先来先服务调度所有进程
    global list,lastid
    list = sorted(list,cmp=lambda x,y:cmp(x[ARRIVE],y[ARRIVE]))#按到达时间对就绪队列进行排序
    for i in range(len(list)):
        if list[i][START] =='':#尚未调度
           if list[i][ID]==0:
                list[i][START]=list[i][ARRIVE]
           else:
               list[i][START] =list[i-1][End]
           assert isinstance(list, object)
           list[i][End] = list[i][START] + list[i][SERVER]
           list[i][ZZ] = list[i][End] - list[i][ARRIVE]
           avg = float(list[i][ZZ])/list[i][SERVER]
           list[i][AVGZZ] = ("%.2f" % avg)
    if len(list):
        lastid = len(list)-1
    show_process()



def spf():#短进程优先--所有进程
    global list,lastid#lastid在这里作为每次已调度的进程中最后一个的id
    lastid =-1
    short_early_list=sorted(list,key=lambda x:(x[SERVER],x[ARRIVE]))
    early_short_list=sorted(list,key=lambda x:(x[ARRIVE],x[SERVER]))
    firstnot=[]#存放下一个要调度的进程
    if len(list)==0:
        tkMessageBox.showerror(  message="当前没有进程,不能调度"  )
    else:
        i=0
        times =len(list)
        del list[:]#list只存放已经调度的,要清空
        while(i<times):#一共有times个进程需要调度,要找times次
            for p in range(times):#找出下一个要调度的进程赋给firstnot
                if len(list)==0:#如果当前时间是0,取时间最早那个--并且在这个时间点上最短的
                    firstnot = early_short_list[0]#取早且短那个
                    #清除两个未调度队列中的firstnot:
                    utid = early_short_list[0][ID]
                    for j in range(len(short_early_list)):#从未调度队列short_early_list中删除
                        if short_early_list[j][ID]==outid:
                            del short_early_list[j]
                            break
                        if j == times-i-2:#防止index溢出
                            break
                    del early_short_list[0]#从未调度队列early_short_list中删除
                    break#一旦找到就跳出for循环
                elif short_early_list[p][ARRIVE]<=list[lastid][End]:#如果前已有调度,且未调度中最短的那个进程已经到达
                    firstnot =short_early_list[p]#就去当前 短且早的这个
                    #清除两个未调度队列中的firstnot:
                    id=short_early_list[p][ID]
                    lenss=len(short_early_list)
                    j=0
                    for k in range(lenss):
                        if short_early_list[k][ID]==id:
                            del short_early_list[k]
                            j +=1
                        if early_short_list[k][ID]==id:
                            del early_short_list[k]
                            j+=1
                        if j == 2 or k >= times-i-2:#防止index溢出
                            break
                    break#一旦找到就跳出for循环
            if firstnot==[]:#如果循环完了都没找到已经到达的进程,那就取接下来最早且短那个
                firstnot = early_short_list[0]#取早且短那个
                #清除两个未调度队列中的firstnot:
                utid = early_short_list[0][ID]
                for x in range(len(short_early_list)):#从未调度队列short_early_list中删除
                    if short_early_list[x][ID]==outid:
                        del short_early_list[x]
                del early_short_list[0]#从未调度队列early_short_list中删除
            #处理firstnot:
            id = len(list)
            arrive = firstnot[ARRIVE]
            server = firstnot[SERVER]
            if lastid ==-1:
                start=firstnot[ARRIVE]
                en= firstnot[ARRIVE] + firstnot[SERVER]
            else:
                start = list[lastid][End]
                en = start+server
            zz = en - arrive
            av = float(zz)/server
            avg = ("%.2f" % av)
            new=[id,'',arrive,server,start,en,zz,avg]
            list.append(new)#在已调度队列list中插入
            lastid = len(list)-1
            i +=1#回到while找下一调度进程
        #调度完成
        show_process()

def rr():#时间片轮转法
    global list,lastid,timestep
    lt = sorted(list,cmp=lambda x,y:cmp(x[ARRIVE],y[ARRIVE]))#按到达时间对队列进行排序,lt指没调度过的进程队列--新来的队列
    del list[:]#完成后的进程才能放进list--完成队列
    worklist=[]#有序存放可调度进程的队列--工作队列
    now = lt[0][ARRIVE] #当前时刻
    alltime=0#要运行的总时
    for i in range(len(lt)):
        lt[i][LE]=lt[i][SERVER]#用LE索引处作为剩余服务时间的记录
        alltime += lt[i][SERVER]
    if now !=0:
        tkMessageBox.showerror(  message="手动输入请从让开始时间为0"  )
    #三步:
    lt[0][START]=lt[0][ARRIVE]
    worklist.append(lt[0])
    del lt[0]
    k=0#用来防止lt越界访问
    lk =len(lt)#用来防止lt越界访问
    while(now < alltime):#没运行完都要继续
        #1、调度worklist队首一个。
        if worklist[0][LE] >= timestep:#如果剩余时间 >= timestep
            worklist[0][LE] -= timestep
            now += timestep
        elif 0 < worklist[0][LE] < timestep:#如果剩余时间不足 timestep
            now += worklist[0][LE]
            worklist[0][LE] = 0
        #2、(如果lt!=[])看lt里哪些进程准备好了,就从lt删除并插进 worklist 里。
        for j in range(len(lt)):
            if lt[j][ARRIVE] <= now:
                lt[j][START] = now
                worklist.append(lt[j])
                del lt[j]
                k += 1
            if j >= lk - k - 1:#防止越界访问
                break

        #3、 把当前调度的从worklist队首删除,如果还没完成就插到 worklist 队尾,如果完成了就插到list队列队尾。
        if worklist[0][LE]==0:
            #先结算
            worklist[0][End] = now
            worklist[0][ZZ] = worklist[0][End] - worklist[0][ARRIVE]
            avg = float(worklist[0][ZZ])/worklist[0][SERVER]
            worklist[0][AVGZZ] = ("%.2f" % avg)
            #再删插
            list.append(worklist[0])
            del worklist[0]
        elif worklist[0][LE]>0:
            worklist.append(worklist[0])
            del worklist[0]
    list = sorted(list,cmp=lambda x,y:cmp(x[ARRIVE],y[ARRIVE]))#按到达时间对队列进行排序,lt指没调度过的进程队列--新来的队列
    show_process()



def algorithm():#采用何种算法
    global message_change
    if r.get() == '1':
        fcfs()
    elif r.get() == '2':
        spf()
    else :
        rr()


from Tkinter import *
top = Tk() #根窗口
top.title=('进程调度')
top.resizable(False, False)
top.geometry('450x500')
c1=Label(top,text='操作')
b1=Button(top,text = "随机初始进程",bg = "SkyBlue",width=15,command = random_process)
c2=Label(top,text='添加进程')
c22=Label(top,text='时间片:')
c23=Label(top,text='到达时间:')
c24=Label(top,text='服务时间:')
c26=Label(top,text='*')
c27=Label(top,text='*')
etime=Entry(width=5)
etime.insert(1,'1')
eat=Entry(width=5)
est=Entry(width=5)
b2=Button(top,text = "确定添加",bg = "SkyBlue",width=15,command = add_process)
c1.place(x=5,y=5)
b1.place(x=5,y=30)
c2.place(x=5,y=60)
c22.place(x=10,y=80)
c23.place(x=10,y=100)
c24.place(x=10,y=120)
etime.place(x=80,y=80)
eat.place(x=80,y=100)
est.place(x=80,y=120)
c26.place(x=120,y=100)
c27.place(x=120,y=120)
b2.place(x=5,y=145)
c3=Label(top,text='选择算法')
c3.place(x=200,y=5)
r = StringVar()                 #使用StringVar生成字符串变量用于单选框组件
r.set('1')                      #初始化变量值
radio = Radiobutton(top,       #生成单选框组件
                            variable = r, #设置单选框关联的变量
                            value = '1',   #设置选中单选框时其所关联的变量的值
                            indicatoron = 0,
                             bg = "SkyBlue",
                            text = '先来先服务'.center(25)) #设置单选框显示的文本
radio.place(x=200,y=30)
radio = Radiobutton(top,
                            variable = r,
                            value = '2',      #当选中单选框时,r的值为2
                            indicatoron = 0,
                            bg = "SkyBlue",
                            text = '短进程优先'.center(25))
radio.place(x=200,y=70)
radio = Radiobutton(top,
                            variable = r,
                            value = '3',
                            indicatoron = 0,
                             bg = "SkyBlue",
                            text = '时间片轮转法'.center(25))
radio.place(x=200,y=110)

b3=Button(top,text = "开始调度",bg = "LightSalmon",width=15,command = algorithm)
b3.place(x=200,y=145)

v1 = StringVar()
v1.set(titlebar)
Message(top,width = 580,textvariable = v1,bg = "Tan" ).place(x=5,y=185)

auth=Label(top,text='进程调度实验\n 11级计科3班\n3211005813\n 青春痘\n  2013年12月28日',bg="LightGrey")
auth.place(x=340,y=0)

mainloop()


TAG:

 

评分:0

我来说两句

我的栏目

日历

« 2024-05-06  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 6767
  • 日志数: 7
  • 建立时间: 2014-02-23
  • 更新时间: 2014-03-10

RSS订阅

Open Toolbar