单处理器调度c语言程序,Linux单处理器进程调度c语言描述

本次实现的是模拟在单处理器情况下的处理器调度,目的是设计一个按优先数调度算法实现处理器调度的程序。

每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:

进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。

指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。

要求运行时间——假设进程需要运行的单位时间数。

优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。

状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。

#include

#include

#include

#include

#include

#include

#include

#define NAMEMAX 64

#define PROCMAX 64

typedef enum Status{

R, //就绪

E //结束

}Status;

typedef struct Proc{

char name[NAMEMAX];//进程名

char next[NAMEMAX];//下一个需要调度的进程的名字

size_t run_time; //要求运行时间

int prio_num; //优先数

Status status; //状态

}Proc;

typedef struct ProcQueue{//进程队列结构体

Proc* data; //指向在堆上动态开辟的内存空间,用来存放进程控制块

size_t size; //队列中有效进程的个数

size_t capatity; //队列的最大容量,如果数据达到最大容量,就要重新开辟一块更大的内存

}ProcQueue;

//进程队列初始化

void ProcQueueInit(ProcQueue* queue)

{

if(queue == NULL)

{

return;

}

queue->size = 0;

queue->capatity = 100;

queue->data = (Proc*)malloc(sizeof(Proc)*queue->capatity);

assert(queue->data != NULL);

}

//销毁进程队列

void DestroyProcQueue(ProcQueue* queue)

{

if(queue == NULL)

{

return;

}

free(queue->data);

queue->size = 0;

queue->capatity = 0;

}

void ProcQueuePush(ProcQueue* queue,Proc pro);

//创建进程对象

void CreateProc(ProcQueue* queue, Proc* pro,size_t n)

{

if(pro == NULL)

{

return;

}

strcpy(pro->next,pro->name);

size_t i = 0;

printf("请输入进程编号(如P1,P2,P3)...\n");

for(; i < n; ++i)

{

scanf("%s",pro->name);

pro->status = R;

srand((unsigned)time(NULL));//采用随机数法为每个进程输入对应数据

pro->prio_num = rand()%6+1;

pro->run_time = rand()%6+1;

ProcQueuePush(queue,*pro);

}

}

//如果当前进程队列满了,就要动态扩容

Proc* ProcQueueExpand(ProcQueue* queue)

{

if(queue == NULL)

{

return NULL;

}

Proc* new_proc = (Proc*)malloc(sizeof(Proc)*2*queue->capatity+1);

queue->capatity = 2*queue->capatity + 1;

size_t i = 0;

for(; i < queue->size ; i++)

{

new_proc[i] = queue->data[i];

}

free(queue->data);

return new_proc;

}

//对进程队列进行冒泡排序

void ProcQueueBubble(ProcQueue* queue)

{

if(queue == NULL)

{

return;

}

size_t i = 0;

Proc tmp;

for(;i < queue->size;i++)

{

size_t j = 0;

for(; j < queue->size-i-1;j++)

{

if(queue->data[j].prio_num < queue->data[j+1].prio_num)

{

tmp = queue->data[j];

queue->data[j] = queue->data[j+1];

queue->data[j+1] = tmp;

}

}

}

}

//插入进程

void ProcQueuePush(ProcQueue* queue, Proc pro)

{

if(queue == NULL)

{

return;

}

if(queue->size == queue->capatity)

{

//进程队列满了,进行动态扩容

queue->data = ProcQueueExpand(queue);

}

//先插入到队列尾部,然后进行排序

//每次的进程队列都是排好序的

//如果新插入的进程状态为结束,就不进行排序

if(pro.status != E)

{

queue->data[queue->size++] = pro;

ProcQueueBubble(queue);

size_t i = 0;

for(; i < queue->size;i++)

{

if(i+1 == queue->size && queue->data[i+1].status != E)

{

strcpy(queue->data[i].next,queue->data[0].name);

}

else

{

strcpy(queue->data[i].next,queue->data[i+1].name);

}

}

}

else

{

strcpy(pro.next," ");

queue->data[queue->size] = pro;

}

}

//进程调度

void ProcQueueRun(ProcQueue* queue)

{

if(queue == NULL )

{

return;

}

if(queue->size != 0)

{

if(queue->data[0].run_time > 0)//进程运行时间大于0才能进行调度

{

queue->data[0].run_time--;//运行时间减一

queue->data[0].prio_num--;//优先级数减一

}

else

{

queue->data[0].status = E;//否则进程状态设置为E

}

Proc run_proc = queue->data[0];

size_t i = 0;

for(;i < queue->size-1;i++)

{

queue->data[i] = queue->data[i+1];

}

queue->size--; //进程调度时相当于出队列,所以要从队列中删除

ProcQueuePush(queue,run_proc); //调度完再入队列

}

}

//打印进程队列信息

void ProcQueuePrint(ProcQueue* queue,size_t n)

{

if(queue == NULL)

{

return;

}

printf("=============================\n");

printf("NAME STATUS RUNTIME NICE NEXT\n");

printf("=============================\n");

size_t i = 0;

for(; i < n ; i++)

{

printf(" %s ",queue->data[i].name);

if(queue->data[i].status == R)

{

printf(" R ");

}else

{

printf(" E ");

}

printf(" %lu ",queue->data[i].run_time);

printf(" %d ",queue->data[i].prio_num);

printf(" %s",queue->data[i].next);

printf("\n");

}

}

int main()

{

ProcQueue queue;

Proc pro;

size_t n = 0;

ProcQueueInit(&queue);

printf("请输入您想拥有的进程数: \n");

scanf("%lu",&n);

CreateProc(&queue,&pro,n);

while(1)

{

if(queue.size == 0)

{

break;

}

printf("\n");

ProcQueuePrint(&queue,n);

getchar();

ProcQueueRun(&queue);

}

ProcQueuePrint(&queue,n);

return 0;

}

处理器系统进程调度 1.实验目的 加深对进程概念的理解,明确进程程序的区别; 深入了解系统如何组织进程、创建进程; 进一步认识如何实现处理器调度。 2.实验预备知识 进程的概念; 进程的组织方式; 进程的创建; 进程的调度。 3.实验内容 编写程序完成处理机系统中的进程调度,要求采用时间片轮转调度算法。实验具体包括:首先确定进程控制的内容,进程控制的组成方式;然后完成进程创建原语和进程调度原语;最后编写主函数对所作工作进程测试。 4.提示与讲解 这个实验主要要考虑三个问题:如何组织进程、如何创建进程和如何实现处理器调度。 考虑如何组织进程,首先就要设定进程控制的内容。进程控制PCB记录各个进程执行时的情况。不同的操作系统进程控制记录的信息内容不一样。操作系统功能越强,软件也越庞大,进程控制记录的内容也就越多。这里的实验只使用了必不可少的信息。一般操作系统中,无论进程控制中信息量多少,信息都可以大致分为以下四类: ① 标识信息 每个进程都要有一个惟一的标识符,用来标识进程的存在和区别于其他进程。这个标识符是必不可少的,可以用符号或编号实现,它必须是操作系统分配的。在后面给出的参考程序中,采用编号方式,也就是为每个进程依次分配一个不相同的正整数。 ② 说明信息 用于记录进程的基本情况,例如进程的状态、等待原因、进程程序存放位置、进程数据存放位置等等。实验中,因为进程没有数据和程序,仅使用进程控制模拟进程,所以这部分内容仅包括进程状态。 ③ 现场信息 现场信息记录各个寄存器的内容。当进程由于某种原因让出处理器时,需要将现场信息记录在进程控制中,当进行进程调度时,从选中进程进程控制中读取现场信息进行现场恢复。现场信息就是处理器的相关寄存器内容,包括通用寄存器、程序计数器和程序状态字寄存器等。在实验中,可选取几个寄存器作为代表。用大写的全局变量AX、BX、CX、DX模拟通用寄存器、大写的全局变量PC模拟程序计数器、大写的全局变量PSW模拟程序状态字寄存器。 ④ 管理信息 管理信息记录进程管理和调度的信息。例如进程优先数、进程队列指针等。实验中,仅包括队列指针。
实验内容: 编写一个处理机下的进程调度程序,模拟操作系统进程的调度。 要求: 能够创建指定数量的进程,每个进程一个进程控制表示。 实现先来先服务调度算法:进程到达时间可由进程创建时间表示。 实现短作业优先调度算法:可指定进程要求的运行时间。(说明:对不可剥夺的短作业优先算法,当作业运行时间相等时,优先调度进程号小的进程执行;对可剥夺式的短作业优先算法,即选最短剩余时间的进程进行运行,在剩余时间相同的情况下,选择到达时间早的进程进行运行) 实现时间片轮转调度算法:可指定生成时间片大小。(说明:新进程到来时插入到就绪队列的队尾,当进程P运行完一个时间片时,若同时有进程Q到达,则先在就绪队列队尾插入新到达的进程Q,之后再插入进程P) 实现动态优先级调度算法:可指定进程的初始优先级(优先级与优先数成反比,优先级最高为0),优先级改变遵循下列原则:进程在就绪队列中每停留一个时间片,优先级加1,进程每运行一个时间片,优先级减3。(说明:本算法在优先级相同的情况下,选择到达时间早的进程进行运行) 测试用例格式如下: 输入:调度算法    进程号/到达时间/运行时间/优先级/时间片 输出:调度顺序/进程号/开始运行时间/结束运行时间/优先级 其中调度算法选项为:1----先来先服务,2----短作业优先,3----最短剩余时间优先,4----时间片轮转,5----动态优先级
实现了如下四种调度算法的模拟: (1)时间片轮转调度 (2)优先数调度 (3)最短进程优先 (4)最短剩余时间优先 模拟过程使用了JProgressBar作为进程状态条,更为直观地观察到每个进程的执行状态。 程序用户说明: 1、在上图标号1处输入要创建随机进程的个数,仅可输入正数,非正数会有相关提示。然后点击标号2处的“创建进程”按钮,随进创建的进程显示在程序界面的中央窗口,如标号3所示。 2、创建好随机进程后,在标号4的选框选择将要模拟执行的调度算法,然后点击标号5处的“开始模拟”,程序开始执行。标号3的列表会显示相应的调度变化。 3、模拟过程中,可以继续添加新的进程,操作同上。 4、 一个算法模拟执行完毕之后,可以点击标号6的“复位”按钮,可以重置列表的内容为程序模拟运行前的内容。复位成功后,可以继续选择其他调度算法进行模拟。 5、标号7显示为程序模拟过程中的时间,从1秒开始累计。 6、点击标号8的“清空”按钮,可以清空类别的进程,以便程序的下次执行。 题目要求: 题目四 处理器系统进程调度 一 、 课 程 设 计 目 的 1. 加深对进程概念的理解, 明确进程程序的区别。 2. 深入了解系统如何组织进程、 创建进程。 3. 进一步认识如何实现处理器调度。 二 、 课 程 设 计 内 容 编写程序完成处理器系统中的进程调度, 要求实现时间片轮转、 优先数、 最短进程优 先和最短剩余时间优先四种调度算法。 实验具体包括: 首先确定进程控制的内容, 进程控 制的组成方式; 然后完成进程创建原语和进程调度原语; 最后编写主函数对所作工作进行 测试。 模拟程序只对你所设置的“ 虚拟 PCB” 进行相应的调度模拟操作, 即每发生“ 调度” 时, 显示出当前运行进程的“ 进程标识符”、“ 优先数”、“ 剩余运行时间” 等, 而不需要对系 统中真正的 PCB 等数据进行修改。
首先,需要定义一个进程的结构体,包含进程名、进程优先数、进程状态等信息: ```c #define MAX_PROCESS_NUM 100 // 最大进程数 #define PROCESS_NAME_LEN 20 // 进程名长度 typedef struct { int pid; // 进程ID char name[PROCESS_NAME_LEN]; // 进程名 int priority; // 进程优先数 int state; // 进程状态,0表示就绪,1表示运行,2表示阻塞 } PCB; PCB process_list[MAX_PROCESS_NUM]; // 进程列表 int process_num = 0; // 当前进程数 ``` 接下来,可以实现一个按优先数调度的函数,该函数按照进程的优先数从高到低排序,然后选择优先数最高的进程执行: ```c void schedule() { int i, j; PCB tmp; // 按优先数从高到低排序 for (i = 0; i < process_num - 1; i++) { for (j = i + 1; j < process_num; j++) { if (process_list[i].priority < process_list[j].priority) { tmp = process_list[i]; process_list[i] = process_list[j]; process_list[j] = tmp; } } } // 选择优先数最高的进程执行 int running_pid = process_list[0].pid; process_list[0].state = 1; // 执行该进程 // ... } ``` 当一个进程创建时,需要为其分配一个唯一的进程ID,可以使用一个全局变量pid_counter来记录已经分配的最大ID,每次创建新进程时,将pid_counter加1并赋值给新进程的pid: ```c int pid_counter = 0; // 进程ID计数器 int create_process(char* name, int priority) { if (process_num >= MAX_PROCESS_NUM) { printf("Error: too many processes!\n"); return -1; } PCB new_process; new_process.pid = ++pid_counter; strcpy(new_process.name, name); new_process.priority = priority; new_process.state = 0; // 初始状态为就绪 process_list[process_num++] = new_process; // 加入进程列表 return new_process.pid; } ``` 以上是一个的按优先数调度算法实现处理器调度的示例。在实际应用中,还需要考虑更多的情况,例如进程的阻塞和唤醒,进程的时间片轮转等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值