利用C語言實現(xiàn)任務(wù)調(diào)度的示例代碼
前言
這個任務(wù)調(diào)度模塊的實現(xiàn)是形成于畢設(shè)項目中的,用在STM32中,斷斷續(xù)續(xù)跨度2個月實現(xiàn)了一些基本功能,可能后面再做其他項目時會一點點完善起來,也會多學(xué)習(xí)相關(guān)知識來強(qiáng)化模塊的實用性和高效性,畢竟用自己自主實現(xiàn)出來的功能還是蠻舒心的。
任務(wù)調(diào)度模式結(jié)構(gòu)
整體上的結(jié)構(gòu)屬于線性結(jié)構(gòu),結(jié)合鏈表和定時器來實現(xiàn),我使用的是sysTick這個滴答時鐘,1ms的頻率,功能比較簡單,容易理解。
分片
分片的模式,主要體現(xiàn)在函數(shù)分片和時間分片在我之前就有使用在函數(shù)中,主要的思路是,把函數(shù)功能切片,分為幾個小部分,每次執(zhí)行時按次序執(zhí)行小部分,對于沒有時序要求的函數(shù)來說,可以把一個占用CPU大的功能分?jǐn)傞_來實現(xiàn),從而避免有些地方耗時長的問題。對于時間分片,其實就是定時器的一種應(yīng)用,實際上,函數(shù)分片在執(zhí)行的時候已經(jīng)是一種時間分片了,不過現(xiàn)在加上人為的控制在里面了。
下面是函數(shù)分片的一般結(jié)構(gòu):
void func(char *fos,...){
static char step=0;//順序控制變量,自由度比較高,可亂序,可循環(huán),可延遲執(zhí)行
switch(step){
case 0:{
//...
step++;
break;
}
case 1:{
//...
step++;
break;
}
//...
default:{
//step++;//可以借助default實現(xiàn)延時的效果,即跳過幾次空白step
break;
}
}
return;
}
其中添加的參數(shù)變量*fos是必要的,因為就是通過傳入每個任務(wù)的這個標(biāo)志位來判斷是否運行結(jié)束,而其他的參數(shù),就得基于具體任務(wù)做不一樣的處理了。
輪詢
運行框圖

可以看到這個框圖是一個頭尾相連的閉環(huán)結(jié)構(gòu),從頭節(jié)點依次運行到尾節(jié)點后再從頭循環(huán)往復(fù)執(zhí)行下去。
輪詢函數(shù)
void loop_task(void){
static Task_Obj *tasknode;
tasknode=task_curnode->next;//repoint the curnode to the next
if(tasknode==NULL){//tasknode is null,only the headnode have the attr
return;//express the task space is none
}
else if(tasknode->task_type==TYPE_HEAD){//tasknode is headnode
task_curnode=tasknode;
return;
}
else{
if(tasknode->run_type == RUN_WAIT){
//等待型任務(wù),通過ready標(biāo)志來確定是否執(zhí)行,否則就跳過
if(!tasknode->ready){
if(task_curnode->next !=NULL){
task_curnode=task_curnode->next;
return;
}
}
}
if(tasknode->task_status==STATUS_INIT){
tasknode->tickstart=HAL_GetTick();//獲取tick
tasknode->task_status=STATUS_RUN;
}
else if(tasknode->task_status==STATUS_RUN){
if((HAL_GetTick() - tasknode->tickstart) > (uint32_t)tasknode->task_tick){
tasknode->task_name(&(tasknode->task_fos));//run the step task,transfer the fos
tasknode->tickstart+=(uint32_t)tasknode->task_tick;//update the tickstart
}
}
}
if(tasknode->task_fos==FOS_FLAG){
tasknode->ready=0;
if(tasknode->waittask!=NULL){
//置位該任務(wù)綁定的等待的任務(wù)準(zhǔn)備運行標(biāo)志位,標(biāo)識可以準(zhǔn)備運行了
tasknode->waittask->ready=1;
}
//運行結(jié)束就刪掉該任務(wù)
delete_task(tasknode);
}
else if(tasknode->task_fos==FOC_FLAG){
//循環(huán)運行該任務(wù)
tasknode->task_status=STATUS_INIT;//continue running from start
tasknode->task_fos=0;//RESET fos
}
if(task_curnode->next !=NULL){
if(task_curnode->next->run_type==RUN_FORCE) return;//force-type's task
else task_curnode=task_curnode->next;
}
}
其中有幾個運行態(tài)和標(biāo)志位
#define FOS_FLAG 99//運行結(jié)束標(biāo)志 #define FOC_FLAG 100//運行結(jié)束后再次執(zhí)行,相當(dāng)于循環(huán)運行 #define TYPE_NOMAL 0//標(biāo)識一般任務(wù)類型 #define TYPE_HEAD 1//標(biāo)識頭任務(wù)類型 #define TYPE_END 2//標(biāo)識尾任務(wù)類型 #define RUN_NORMAL 0//一般輪詢模式 #define RUN_FORCE 1//強(qiáng)制運行該任務(wù),運行結(jié)束才繼續(xù)下一個任務(wù) #define RUN_WAIT 2//等待指定的任務(wù)結(jié)束,才可以被運行 #define STATUS_INIT 0//任務(wù)的準(zhǔn)備階段,用于獲取起始時間 #define STATUS_RUN 1//任務(wù)運行階段 #define STATUS_UNVAILED 2//無效狀態(tài)
運行時對時間間隔tick的把握還有點問題,這個等待后面有機(jī)會優(yōu)化下。
調(diào)度實現(xiàn)
任務(wù)鏈表結(jié)構(gòu)
typedef struct TASK_CLASS{
void (*task_name)(char *taskfos,...);//任務(wù)函數(shù)
int task_tick;//任務(wù)的時間分片間隔
uint32_t tickstart;//起始時間點,每次執(zhí)行完須加上一個tick
char task_fos;//運行結(jié)束標(biāo)志
char task_type;//任務(wù)類型變量
char task_status;//任務(wù)狀態(tài)
char run_type;//運行狀態(tài)
char ready;//準(zhǔn)備運行標(biāo)志位
struct TASK_CLASS *next;//下一任務(wù)
struct TASK_CLASS *waittask;//等待執(zhí)行的任務(wù)
} Task_Obj;
添加任務(wù)
add_task
void add_task(void (*taskname)(char *,...),int tasktick,int runtype){//可變參,這里未做處理
Task_Obj *tasknode,*tmpnode;
char i;
tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));
tasknode->task_name=taskname;
tasknode->task_tick=tasktick;
tasknode->task_fos=0;
tasknode->task_status=STATUS_INIT;//initial status
tasknode->task_type=TYPE_END; //set the new node to endnode
tasknode->run_type=runtype;
tasknode->next=&task_headnode;//the endnode point to the headnode
tmpnode=&task_headnode;
if(task_num==0){
tmpnode->next=tasknode;
task_num++;
return;
}
for(i=0;i<task_num;i++){
tmpnode=tmpnode->next;//reach the endnode
}
tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal node
tmpnode->next=tasknode;
task_num++;
}
add_wait_task
void add_wait_task(void (*taskname)(char *),void (*waitname)(char *),int tasktick){
Task_Obj *tmpnode,*tasknode;
char i,pos;
tmpnode=&task_headnode;
for(i=0;i<task_num;i++){
tmpnode=tmpnode->next;//reach the endnode
if(tmpnode->task_name==taskname){
pos=i;//獲取要等待任務(wù)的位置
break;
}
}
tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));
tasknode->task_name=waitname;
tasknode->task_tick=tasktick;
tasknode->task_fos=0;
tasknode->task_status=STATUS_INIT;//initial status
tasknode->task_type=TYPE_END; //set the new node to endnode
tasknode->run_type=RUN_WAIT;//任務(wù)為等待運行
tasknode->ready=0;
tasknode->next=&task_headnode;//the endnode point to the headnode
tmpnode->waittask=tasknode;//獲取新建的等待執(zhí)行的任務(wù)地址,在運行結(jié)束后把等待執(zhí)行的任務(wù)的準(zhǔn)備運行標(biāo)志位置1
tmpnode=&task_headnode;
if(task_num==0){
tmpnode->next=tasknode;
task_num++;
return;
}
for(i=0;i<task_num;i++){
tmpnode=tmpnode->next;//reach the endnode
}
tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal node
tmpnode->next=tasknode;
task_num++;
}
刪除任務(wù)
delete_task(局限性大,只針對當(dāng)前運行的任務(wù)而言)
void delete_task(Task_Obj *taskobj){
if(task_curnode->task_type==TYPE_HEAD && task_num < 2){//if curnode is headnode,and tasknum=1
task_curnode->next=NULL;
}
else{
task_curnode->next=taskobj->next;//repoint the curnode next
}
free(taskobj);//free the space of where the taskobj pointed
task_num--;
}
delete_task_withname(刪除指定任務(wù)名的任務(wù))
void delete_task_withname(void (*taskname)(char *)){
Task_Obj *tmpnode,*tmpnode2;
char i,pos;
tmpnode=&task_headnode;
for(i=0;i<task_num;i++){
tmpnode=tmpnode->next;//reach the endnode
if(tmpnode->task_name==taskname){
pos=i;
break;
}
}
if(i==task_num) return;
tmpnode=&task_headnode;
for(i=0;i<pos+1;i++){
tmpnode2=tmpnode;
tmpnode=tmpnode->next;
}
if(tmpnode->next==NULL){//if tmpnode is endnode
tmpnode2->next=&task_headnode;
}
else{
tmpnode2->next=tmpnode->next;//repoint the curnode next
}
task_num--;
free(tmpnode);
}
初始化任務(wù)空間
void non_task(char *taskfos){
return;
}
void init_taskspace(void){
task_headnode.task_name=non_task;
task_headnode.task_type=TYPE_HEAD;
task_headnode.task_status=STATUS_UNVAILED;
task_headnode.next=NULL;
task_curnode=&task_headnode;//頭節(jié)點是沒有任務(wù)需要執(zhí)行的
task_num=0;
}
調(diào)用實例
add_task(task1,500,RUN_NORMAL);//500ms執(zhí)行一次task1任務(wù)
add_wait_task(task1,task2,500);//task2等待task1結(jié)束才會執(zhí)行,運行的時間間隔為500ms
delete_task_withname(task1);//刪除task1任務(wù)
while(1){
//...
loop_task();//任務(wù)輪詢
}
結(jié)語
整體實現(xiàn)說難不難,說簡單不簡單,但也是我第一次嘗試這種偏向系統(tǒng)級應(yīng)用的代碼,而且都沒有參照任何其他的資料和代碼,完全以自己的對任務(wù)的理解和具體項目的需求來一點點實現(xiàn),希望后面會把這個調(diào)度的代碼進(jìn)一步完善成一個通用型的調(diào)度方式,也方便后面項目的使用了。
到此這篇關(guān)于利用C語言實現(xiàn)任務(wù)調(diào)度的示例代碼的文章就介紹到這了,更多相關(guān)C語言任務(wù)調(diào)度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中fstream,ifstream及ofstream用法淺析
這篇文章主要介紹了C++中fstream,ifstream及ofstream用法,適合C++初學(xué)者學(xué)習(xí)文件流的操作,需要的朋友可以參考下2014-08-08
C++ Primer Plus 第四章之C++ Primer Plus復(fù)合類型學(xué)習(xí)筆記
數(shù)組(array)是一種數(shù)據(jù)格式,能夠存儲多個同類型的值。每個值都存儲在一個獨立的數(shù)組元素中,計算機(jī)在內(nèi)存中依次存儲數(shù)組的各個元素,今天給大家重點介紹C++ Primer Plus復(fù)合類型的實例詳解,感興趣的朋友一起看看吧2021-07-07
opencv圖片的任意角度旋轉(zhuǎn)實現(xiàn)示例
這篇博客將介紹如何使用OpenCV旋轉(zhuǎn)圖像任意角度,實現(xiàn)各個角度的旋轉(zhuǎn),具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06

