c语言任务调度函数 任务调度c语言数据结构

用C语言编写一段简单的程序,作业调度和低级调度算法真不容易啊,怕是没人弄了!
优先级调度算法程序:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef struct node
{
char name[10];/*进程标识符*/
int prio;/*进程优先数*/
int round;/*进程时间轮转时间片*/
int cputime; /*进程占用CPU时间*/
int needtime; /*进程到完成还要的时间*/
int count;/*计数器*/
char state; /*进程的状态*/
struct node *next; /*链指针*/
}PCB;
PCB *finish,*ready,*tail,*run; /*队列指针*/
int N; /*进程数*/
/*将就绪队列中的第一个进程投入运行*/
firstin()
{
run=ready;/*就绪队列头指针赋值给运行头指针*/
run-state='R';/*进程状态变为运行态*/
ready=ready-next;/*就绪对列头指针后移到下一进程*/
}
/*标题输出函数*/
void prt1(char a)
{
if(toupper(a)=='P') /*优先数法*/
printf("namecputimeneedtimeprioritystate\n");
else
printf("namecputimeneedtimecountroundstate\n");
}
/*进程PCB输出*/
void prt2(char a,PCB *q)
{
if(toupper(a)=='P')/*优先数法的输出*/
printf("%-10s%-10d%-10d%-10d %c\n",q-name,
q-cputime,q-needtime,q-prio,q-state);
else/*轮转法的输出*/
printf("%-10s%-10d%-10d%-10d%-10d %-c\n",q-name,
q-cputime,q-needtime,q-count,q-round,q-state);
}
/*输出函数*/
void prt(char algo)
{
PCB *p;
prt1(algo);/*输出标题*/
if(run!=NULL) /*如果运行指针不空*/
prt2(algo,run); /*输出当前正在运行的PCB*/
p=ready;/*输出就绪队列PCB*/
while(p!=NULL)
{
prt2(algo,p);
p=p-next;
}
p=finish;/*输出完成队列的PCB*/
while(p!=NULL)
{
prt2(algo,p);
p=p-next;
}
getch();/*压任意键继续*/
}
/*优先数的插入算法*/
insert1(PCB *q)
{
PCB *p1,*s,*r;
int b;
s=q;/*待插入的PCB指针*/
p1=ready; /*就绪队列头指针*/
r=p1; /*r做p1的前驱指针*/
b=1;
while((p1!=NULL)b)/*根据优先数确定插入位置*/
if(p1-prio=s-prio)
{
r=p1;
p1=p1-next;
}
else
b=0;
if(r!=p1)/*如果条件成立说明插入在r与p1之间*/
{
r-next=s;
s-next=p1;
}
else
{
s-next=p1;/*否则插入在就绪队列的头*/
ready=s;
}
}
/*轮转法插入函数*/
insert2(PCB *p2)
{
tail-next=p2;/*将新的PCB插入在当前就绪队列的尾*/
tail=p2;
p2-next=NULL;
}
/*优先数创建初始PCB信息*/
void create1(char alg)
{
PCB *p;
int i,time;
char na[10];
ready=NULL; /*就绪队列头指针*/
finish=NULL;/*完成队列头指针*/
run=NULL; /*运行队列指针*/
printf("Enter name and time of process\n"); /*输入进程标识和所需时间创建PCB*/
for(i=1;i=N;i++)
{
p=malloc(sizeof(PCB));
scanf("%s",na);
scanf("%d",time);
strcpy(p-name,na);
p-cputime=0;
p-needtime=time;
p-state='w';
p-prio=50-time;
if(ready!=NULL) /*就绪队列不空调用插入函数插入*/
insert1(p);
else
{
p-next=ready; /*创建就绪队列的第一个PCB*/
ready=p;
}
}
clrscr();
printf("output of priority:\n");
printf("************************************************\n");
prt(alg);/*输出进程PCB信息*/
run=ready; /*将就绪队列的第一个进程投入运行*/
ready=ready-next;
run-state='R';
}
/*轮转法创建进程PCB*/
void create2(char alg)
{
PCB *p;
int i,time;
char na[10];
ready=NULL;
finish=NULL;
run=NULL;
printf("Enter name and time of round process\n");
for(i=1;i=N;i++)
{
p=malloc(sizeof(PCB));
scanf("%s",na);
scanf("%d",time);
strcpy(p-name,na);
p-cputime=0;
p-needtime=time;
p-count=0; /*计数器*/
p-state='w';
p-round=2;/*时间片*/
if(ready!=NULL)
insert2(p);
else
{
p-next=ready;
ready=p;
tail=p;
}
}
clrscr();
printf("output of round\n");
printf("************************************************\n");
prt(alg);/*输出进程PCB信息*/
run=ready;/*将就绪队列的第一个进程投入运行*/
ready=ready-next;
run-state='R';
}
/*优先数调度算法*/
priority(char alg)
{
while(run!=NULL)/*当运行队列不空时,有进程正在运行*/
{
run-cputime=run-cputime+1;
run-needtime=run-needtime-1;
run-prio=run-prio-3; /*每运行一次优先数降低3个单位*/
if(run-needtime==0)/*如所需时间为0将其插入完成队列*/
{
run-next=finish;
finish=run;
run-state='F';/*置状态为完成态*/
run=NULL;/*运行队列头指针为空*/
if(ready!=NULL) /*如就绪队列不空*/
firstin(); /*将就绪对列的第一个进程投入运行*/
}
else /*没有运行完同时优先数不是最大,则将其变为就绪态插入到就绪队列*/
if((ready!=NULL)(run-prioready-prio))
{
run-state='W';
insert1(run);
firstin(); /*将就绪队列的第一个进程投入运行*/
}
prt(alg); /*输出进程PCB信息*/
}
}
/*时间片轮转法*/
roundrun(char alg)
{
while(run!=NULL)
{
run-cputime=run-cputime+1;
run-needtime=run-needtime-1;
run-count=run-count+1;
if(run-needtime==0)/*运行完将其变为完成态,插入完成队列*/
{
run-next=finish;
finish=run;
run-state='F';
run=NULL;
if(ready!=NULL)
firstin(); /*就绪对列不空,将第一个进程投入运行*/
}
else
if(run-count==run-round)/*如果时间片到*/
{
run-count=0;/*计数器置0*/
if(ready!=NULL) /*如就绪队列不空*/
{
run-state='W'; /*将进程插入到就绪队列中等待轮转*/
insert2(run);
firstin(); /*将就绪对列的第一个进程投入运行*/
}
}
prt(alg); /*输出进程信息*/
}
}
/*主函数*/
main()
{
char algo;/*算法标记*/
clrscr();
printf("type the algorithm:P/R(priority/roundrobin)\n");
scanf("%c",algo); /*输入字符确定算法*/
printf("Enter process number\n");
scanf("%d",N); /*输入进程数*/
if(algo=='P'||algo=='p')
{
create1(algo); /*优先数法*/
priority(algo);
}
else
if(algo=='R'||algo=='r')
{
create2(algo); /*轮转法*/
roundrun(algo);
}
}
用c语言或者Java设计出一个任务调度器 。。。公众:类PrivilegeProcess {
公共静态无效c语言任务调度函数的主要(字串[] args){
MyQueue的MyQueue的新MyQueue的();/ /声明队列
印刷电路板[PCB = {新的PCB(001 c语言任务调度函数 , 8,1),新的PCB(002,7,9),新的PCB(003,3,8),新的PCB(004,1,7),新的PCB(005,7,4)};
PCB段=新的PCB();
(INT I = 0; pcb.length; + +){/ /初始化先进行排序,选择排序这里使用的是高优先级的一线队
(J =我; pcb.length; J + +){
(PCB [I] 。特权PCB [J] 。特权){
段= PCB [1];
PCB [I] = PCB [J];
PCB [J] =段;
}
}
}
体系 。通过out.println(“入队后第一时间的进程的顺序:”);
(INT I = 0; pcb.length; + +){
的System.out调用println(第一次入队#程序名称:“+ PCB [我] 。名称+ totaltime:”+ PCB [I] 。totaltime +“的”特权“+ PCB [我] 。特权); }
();
myqueue.start(PCB);
}
}
类MyQueue的{
INT指数= 0;
PCB [] PC =新的PCB [5];
PCB [] PC1 =新的PCB [4];
PCB温度=新的PCB() BR /公共无效排队(PCB工艺){/ /排队算法
(指数== 5){
(“出界!”);
返回
}
PC [索引] =进程;
指数+ +;
}
公共:PCB DEQUEUE(){/ /出队算法(索引== 0)
返回空;
(INT I = 0; pc1.length; + +){
PC1 [I] = PC [ +1];
}
指数 -
温度= PC [0];
(INT I = 0; pc1.length; + +){ BR / PC [I] = PC1 [I];
}
回报条件;
}
公共无效启动(PCB [] PC){/ /进程表算法
(PC [0] 。isNotFinish ==真| | PC [1 isNotFinish ==真| | PC [2 isNotFinish ==真| | PC [3] 。时isNotFinish ==真| | PC [4] 。isNotFinish ==){
/ / *注:| |运算符都是假的 , 所有的表达式结果为假,否则真
(INT I = 0; PC长度; + +){
PC [I] 。运行(这一点); /} 的System.out.println();
(INT I = 0; pc.length; + +){/ /处理每个运行一次运行的时间片的长度重新排序优先一旦
(J =我; pc.length; J + +){
如果(PC [I]特权PC [J] 。特权){
温度= PC [I];
PC [I] = PC [J];
PC [J] =温度;
}
}
}
}
}
}
类PCB {/ /声明过程级
和int名,totaltime,运行时特权;
布尔isNotFinish的;
公众PCB(){
}
公开PCB(名称,诠释totaltime特权){
this.name =的名称;/ /进程名
this.totaltime = totaltime ;/ /
this.privilege =特权;/ /总时间优先 this.runtime = 2 ;/ /时间片值是2
this.isNotFinish =真;/ /是否执行完成
(“初始值:程序名称:”+名+“totaltime:”+ totaltime +“特权”+特权);
System.out的 。调用println();
}
MyQueue的MQ公共无效的run(){/ /处理的基础上实施的时间片算法
(totalTime 1){ totaltime =运行;/ /总时间大于1 , 总时间=总时间 - 时间片
特权 -
(“程序名称:”+姓名+“ remaintime:“+ +”特权“+特权); totaltime
的} else if(totaltime == 1){
totaltime - ;/ /总时间为1时 , 执行时间为1
特权 -
(“程序名称:”+姓名+“remaintime:”+ totaltime +“特权”+特权);
}其他{
isNotFinish =假;/ / 0,将isNotFinish标志设置为假
}
如果(isNotFinish ==真){br mq.deQueue();mq.enQueue(本); }
}
}
如何编写一个最简单的嵌入式操作系统简单任务调度最简单的任务调度
以现代观点而言 , 一个标准个人电脑的OS应该提供以下的功能:
进程管理(Processing management)
内存管理(Memory management)
文件系统(File system)
网络通讯(Networking)
安全机制(Security)
用户界面(User interface)
驱动程序(Device drivers)
但一个最简易的嵌入式操作系统,所包含的可以少很多 。最简单的操作系统,通常都是围绕着进程管理展开的 。所以,现在可以尝试下一个最简单的“操作系统”,只能做简单地进行人工任务调度 。为了简单起见,使用最简单的AT89S52运行程序:内存小的数的清字节数,外设只有几个IO,结构简单,很方便操作系统的编写 。
1.裸跑的任务和操作系统中的任务
相信大家都很熟悉,用单片机裸跑,程序一般都写成如下一个大的while死循环:
void main (void)
{
while (1) /* repeat forever */
{
do_something();
}
}
或者又像:
void main (void)
{
while (1) /* repeat forever */
{
do_something1();
do_something2(); //Catch data input
do_something3();
.
.
.
}
}
这里每一个函数完成一个独立的操作或者任务,这些函数(也可以叫任务)以一定的顺序执行,一个接着一个 。这里的任务切换,单纯就是执行完一个 , 再执行另一个 。不断循环 。
但是,一旦增加更多的任务,那么执行的顺序就变成了一个问题 。在以上的例子中,一旦函数do_something1()运行了太长的时间,那么主循环就需要很长的时间才可以执行到do_something2() 。如果do_something2()是接收输入数据的函数,数据就很有可能丢失 。当然 , 我们也可以在循环中插入更多的do_something2()函数调用 , 或者把do_something1()拆分成几个比较小的部分 。但这就比较考验编程者功力了,如果任务太多,编写程序将成为一个相当复杂的问题 。
这时,一个帮助你分配各个任务运行时间的操作系统就很有必要了 。在操作系统中,任务一般形如:
void check_serial_io_task (void) _task_ 1
{
/* This task checks for serial I/O */
}
void process_serial_cmds_task (void) _task_ 2
{
/* This task processes serial commands */
}
void check_kbd_io_task (void) _task_ 3
{
/* This task checks for keyboard I/O */
}
任务之间的切换已经交给操作系统完成了,熟悉的main函数和while(1)一般已经隐去不见了 。
2.如何做任务切换
还是说单片机裸跑,裸跑时 , 把C语言文件编译成汇编,可以看到,是用CALL指令去调一个任务函数,执行完毕后,用RET退出 。但是这样的方法用在切换频繁的操作系统中 , 就无疑不适合了,因为我们无法做到预知什么时候退出,即调用RET 。
任务切换,看起来很玄,实际上说白了,就是改变程序指针PC的值 。前边写的_task_ 1,_task_ 2,编译以后,都存储在ROM中 。把PC指向这段ROM,他就执行了,想切换另一个任务,就用PC指向那个任务 。就这么简单 。这样说,是不是就是PC=一个地址就可以了?不行,因为绝大多数单片机,是不允许给PC寄存器直接赋值的 。那样写 , 编译器会报错的 。一般操作系统,都用以下方法改变PC的值:
unsigned char Task_Stack1[3];
Task_Stack1[1] = (uint16) Task_1;
Task_Stack1[2] = (uint16) Task_18;
SP = Task_Stack1+2;
}//编译成RET
PC的值不能直接改变 , 但是可以变通,通过其他方式改变PC的值 。一个函数执行完毕 , 总是要改变PC的 。这是 , PC是如何改变的呢?函数执行前,PC被压入了堆栈中 。函数结束,要调用的是RET指令,也就是PC出栈 。压在堆栈中的原始PC值 , 这时从堆栈中弹出,程序又回到了原来的位置 。这里就是模仿这一过程:模拟一个堆栈的结构,把要执行的函数入口地址(C语言中的函数名)装入其中,把SP指向这个自己创建的堆栈栈顶 。一个RET指令,就将[SP]和[SP-1]弹到PC中了 。就这样,PC改变到了要执行的函数入口地址 , 开始执行目标函数 。(AT89s52的PC为16位 , 压到堆栈中是两个字节)
3.一个最简单的人工调度系统
应用上面的思想,写一个最简单的3任务人工调度系统 。代码如下:
typedef unsigned char uint8;
typedef unsigned int uint16;
#include
sbit led0 = P0^0;
sbit led1 = P0^1;
sbit led2 = P0^2;
uint8 Cur_TaskID; //当前运行的任务号
uint8 Task_Stack0[10]; //0号任务的堆栈
uint8 Task_Stack1[10];
uint8 Task_Stack2[10];
uint8 Task_StackSP[3]; //3个堆栈的栈顶指针
//Task_StackSP[0] - Task_Stack0
//Task_StackSP[1] - Task_Stack1
//Task_StackSP[2] - Task_Stack2
void Task_0(); //任务0
void Task_1(); //任务1
void Task_2(); //任务2
void Task_Scheduling(uint8 Task_ID); //任务调度
void main (void)
{
Task_Stack0[1] = (uint16) Task_0; //按照小端模式 , 任务函数入口地址装入任务堆栈
Task_Stack0[2] = (uint16) Task_08;
Task_Stack1[1] = (uint16) Task_1;
Task_Stack1[2] = (uint16) Task_18;
Task_Stack2[1] = (uint16) Task_2;
Task_Stack2[2] = (uint16) Task_28;
Task_StackSP[0] = Task_Stack0;
Task_StackSP[0] += 2; //刚入栈两个元素 。这里取得栈顶地址,即Task_Stack0[2]
Task_StackSP[1] = Task_Stack1;
Task_StackSP[1] += 2;
Task_StackSP[2] = Task_Stack2;
Task_StackSP[2] += 2;
Cur_TaskID = 0;
SP = Task_StackSP[0]; //SP取得0号任务的栈顶地址
}//利用main的返回指令RET,使PC取得0号任务入口地址
//任务调度函数
void Task_Scheduling(uint8 Task_ID)
{
Task_StackSP[Cur_TaskID] = SP;
Cur_TaskID = Task_ID;
SP = Task_StackSP[Cur_TaskID];
}
//0号任务函数
void Task_0()
{
while(1)
{
led0 = 0;
Task_Scheduling(1);
}
}
//1号任务函数
void Task_1()
{
while(1)
{
led1 = 0;
Task_Scheduling(2);
}
}
//2号任务函数
void Task_2()
{
while(1)
{
led2 = 0;
Task_Scheduling(0);
}
}
代码要做的,就是3个任务的顺序执行 。任务调度函数Task_Scheduling的思想也即如前面所述 。在Keil中可以运行代码,可以看到,程序在3个任务中顺序执行了 。
c语言怎样从底层实现任务调度对于何时调度的问题c语言任务调度函数,如果在用户态线程中用如时间片轮转这样的调度方式来调度,注定任务的数量不不会太多 , 这样还不如用操作系统提供的多
线程 。一般coroutine用于任务数量巨大,并且任务存在大量的I/O操作的场景 , 例如Python的gevent 。这需要在实现基本的
coroutine的同时完成一套与之配合的异步I/O库 , 可以在当前coroutine运行到I/O操作时交出CPU给其c语言任务调度函数他coroutine
如何切换的问题上,Windows可以用fiber,Posix兼容的系统可以使用set/getcontext
【c语言任务调度函数 任务调度c语言数据结构】关于c语言任务调度函数和任务调度c语言数据结构的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息 , 记得收藏关注本站 。

    推荐阅读