操作系统实验指导书
和client,进行通信。
2、server端建立一个key为75的共享区,并将第一个字节置为-1,作为数据空的标志。等待其他进程发来的消息。当该字节的值发生变化时,表示收到了信息,进行处理。然后再次把它的值设为-1,如果遇到的值为0,则视为为结束信号,取消该队列,并退出server。server每接收到一次数据后显示“(server)received”。
3、client端建立一个key为75的共享区,当共享取得第一个字节为-1时,server端空闲,可发送请求。client随即填入9到0。期间等待 server 端的再次空闲。进行完这些操作后,client退出。client每发送一次数据后显示“(client)sent”。
4、父进程在server和client均退出后结束。
五、运行结果
和预想的完全一样。但在运行过程中,发现每当client发送一次数据后,server要等待大约0.1秒才有响应。同样,之后client又需要等待大约0.1秒才发送下一个数据。
六、程序分析
出现上述应答延迟的现象是程序设计的问题。当client端发送了数据后,并没有任何措施通知server端数据已经发出,需要由client的查询才能感知。此时,client端并没有放弃系统的控制权,仍然占用CPU的时间片。只有当系统进行调度时,切换到了server进程,再进行应答。这个问题,也同样存在于server端到client的应答过程中。
七、思考题
1、比较两种消息通信机制中数据传输的时间 由于两种机制实现的机理和用处都不一样,难以直接进行时间上的比较。如果比较其性能,应更加全面的分析。
(1)消息队列的建立比共享区的设立消耗的资源少。前者只是一个软件上设定的问题,后者需要对硬件的操作,实现内存的映像,当然控制起来比前者复杂。如果每次都重新进行队列或共享的建立,共享区的设立没有什么优势。
(2)当消息队列和共享区建立好后,共享区的数据传输,受到了系统硬件的支持,不耗费多余的资源;而消息传递,由软件进行控制和实现,需要消耗一定的cpu的资源。从这个意义上讲,共享区更适合频繁和大量的数据传输。
(3)消息的传递,自身就带有同步的控制。当等到消息的时候,进程进入睡眠状态,不再消耗cpu资源。而共享队列如果不借助其他机制进行同步,接收数据的一方必须进行不断的查询,白白浪费了大量的cpu资源。可见,消息方式的使用更加灵活。
41
操作系统实验指导书
实验四 进程调度
实验目的
通过优先级调度算法和时间片轮转调度算法的模拟加深进程概念和进程调度过程的理解。
实验内容
1、设计进程控制块PCB表结构,分别适用于优先级调度算法和时间片轮转调度算法。 2、建立进程就绪队列。
3、编制两种进程调度算法:优先级调度算法(即把处理机分配给优先数最高的进程)和时间片轮转调度算法。
实验指导
一、实验提示
1、用C语言来实现对N个进程分别采用优先级调度算法(即把处理机分配给优先数最高的进程)和时间片轮转调度算法(时间片为两个单位时间)的进程调度。
2、设计进程控制块PCB的结构,分别适用于优先级调度算法和时间片轮转调度算法。PCB包括以下字段:
? 进程标识数id;
? 进程优先数priority(用于优先级调度算法),并规定优先数越大的进程,其优
先权越高;
? 进程已占用的CPU时间cputime;
? 进程还需占用的CPU时间needtime,当进程运行完毕时,needtime变为0; ? 进程运行时间片计数count(用于时间片轮转调度算法);
? 进程状态state。state为枚举类型,包括ready,execute,block,finish四种状
态。
? 队列指针next,用来将PCB排成队列。 3、优先数改变的原则:
进程每运行一个时间片(一个单位时间),优先数减3。 4、假设在调度前,系统中有5个进程,它们的初始状态如下: id 0 1 2 3 4 cputime 0 0 0 0 0 needtime 2 3 6 5 4 count 0 0 0 0 0 state ready ready ready ready ready priority=50-needtime (即需求时间越大,优先权越低) 5、为了清楚地观察诸进程的调度过程,程序应将每个时间片内的进程的情况显示出来,参照格式如下:
id cputime needtime priority(count) state 0 0 2 48 ready 1 0 3 47 ready 2 0 6 44 ready 3 0 5 45 ready 4 0 4 46 ready
二、参考程序
#include
42
操作系统实验指导书
#include
#define P_NUM 5 //进程个数
#define P_TIME 50 //允许进程运行的最长时间
//进程状态
enum pstate{ ready, execute, block, finish
};
//进程控制块 struct spcb{ int id; int priority; int cputime; int needtime;
int count; //时间片轮转调度算法中,进程已运行的 时间片个数 enum pstate state; struct spcb *next; };
typedef struct spcb pcb;
void display_menu(){ printf(\ printf(\ printf(\ printf(\}
//创建进程-优先级调度算法 pcb* get_process_priority(){ pcb *q; pcb *head; pcb *tail; int i = 0;
printf(\
while (i < P_NUM){ q=(pcb *)malloc(sizeof(pcb)); scanf(\
scanf(\
43
操作系统实验指导书
q->cputime = 0;
q->priority = P_TIME - q->needtime; //需求时间越大,优先级越低 q->state = ready; q->next = NULL; if(i==0){ head= q; tail = q;
} else{ tail->next = q; tail = q; } i++;
}
return head;
}
//释放队列中所有进程,p 为队列头指针 void free_process(pcb *p) { pcb *q;
while(p!= NULL){ q = p; p = p->next; free(q);
}
}
//显示所有进程当前状态信息 void display_priority(pcb *p){ printf(\ cputime needtime priority state\\n\ while(p){ printf(\ printf(\ \ printf(\ printf(\ \ printf(\ printf(\ \ printf(\ printf(\ \ switch(p->state){ case ready:printf(\ case execute:printf(\
case block:printf(\
44
操作系统实验指导书
case finish:printf(\
}
p = p->next;
}
}
//判断队列中所有进程是否已运行完毕 int process_finish(pcb *p){ int finish = 1; while(finish&&p){ finish = finish&&p->needtime==0; p = p->next;
}
return finish;
}
void set_state(pcb *p){ while(p){ if(p->needtime == 0){ p->state = finish;
}
if(p->state == execute){ p->state = ready; }
p = p->next;
}
}
//选择一个优先级最高的进程执行一个单位时间,p 为队列头指针void cpuexe_priority(pcb *p) { pcb *t = q; int tp = 0;
while(q){ //让t指向优先级最高的进程 if (q->process!=finish){ q->process = ready; if(q->needtime==0){ q->process = finish; }
}
if(tp
}
45