欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用C語言實現(xiàn)任務調度的示例代碼

 更新時間:2023年04月10日 08:45:17   作者:pie_thn  
這篇文章主要為大家詳細介紹了如何利用純C語言實現(xiàn)任務調度(可用于STM32、C51等單片機),文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下

前言

這個任務調度模塊的實現(xiàn)是形成于畢設項目中的,用在STM32中,斷斷續(xù)續(xù)跨度2個月實現(xiàn)了一些基本功能,可能后面再做其他項目時會一點點完善起來,也會多學習相關知識來強化模塊的實用性和高效性,畢竟用自己自主實現(xiàn)出來的功能還是蠻舒心的。

任務調度模式結構

整體上的結構屬于線性結構,結合鏈表和定時器來實現(xiàn),我使用的是sysTick這個滴答時鐘,1ms的頻率,功能比較簡單,容易理解。

分片

分片的模式,主要體現(xiàn)在函數(shù)分片和時間分片在我之前就有使用在函數(shù)中,主要的思路是,把函數(shù)功能切片,分為幾個小部分,每次執(zhí)行時按次序執(zhí)行小部分,對于沒有時序要求的函數(shù)來說,可以把一個占用CPU大的功能分攤開來實現(xiàn),從而避免有些地方耗時長的問題。對于時間分片,其實就是定時器的一種應用,實際上,函數(shù)分片在執(zhí)行的時候已經是一種時間分片了,不過現(xiàn)在加上人為的控制在里面了。

下面是函數(shù)分片的一般結構:

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必要的,因為就是通過傳入每個任務的這個標志位來判斷是否運行結束,而其他的參數(shù),就得基于具體任務做不一樣的處理了。

輪詢

運行框圖

可以看到這個框圖是一個頭尾相連的閉環(huán)結構,從頭節(jié)點依次運行到尾節(jié)點后再從頭循環(huán)往復執(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){
            //等待型任務,通過ready標志來確定是否執(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){
            //置位該任務綁定的等待的任務準備運行標志位,標識可以準備運行了
			tasknode->waittask->ready=1;
		}
        //運行結束就刪掉該任務
		delete_task(tasknode);
	}
	else if(tasknode->task_fos==FOC_FLAG){
        //循環(huán)運行該任務
		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)和標志位

#define FOS_FLAG 99//運行結束標志
#define FOC_FLAG 100//運行結束后再次執(zhí)行,相當于循環(huán)運行
#define TYPE_NOMAL 0//標識一般任務類型
#define TYPE_HEAD 1//標識頭任務類型
#define TYPE_END 2//標識尾任務類型
#define RUN_NORMAL 0//一般輪詢模式
#define RUN_FORCE 1//強制運行該任務,運行結束才繼續(xù)下一個任務
#define RUN_WAIT 2//等待指定的任務結束,才可以被運行
#define STATUS_INIT 0//任務的準備階段,用于獲取起始時間
#define STATUS_RUN 1//任務運行階段
#define STATUS_UNVAILED 2//無效狀態(tài)

運行時對時間間隔tick的把握還有點問題,這個等待后面有機會優(yōu)化下。

調度實現(xiàn)

任務鏈表結構

typedef struct TASK_CLASS{
	void (*task_name)(char *taskfos,...);//任務函數(shù)
	int task_tick;//任務的時間分片間隔
	uint32_t tickstart;//起始時間點,每次執(zhí)行完須加上一個tick
	char task_fos;//運行結束標志
	char task_type;//任務類型變量
	char task_status;//任務狀態(tài)
	char run_type;//運行狀態(tài)
	char ready;//準備運行標志位
	struct TASK_CLASS *next;//下一任務
	struct TASK_CLASS *waittask;//等待執(zhí)行的任務
} Task_Obj;

添加任務

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;//獲取要等待任務的位置
		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;//任務為等待運行
tasknode->ready=0;
tasknode->next=&task_headnode;//the endnode point to the headnode

tmpnode->waittask=tasknode;//獲取新建的等待執(zhí)行的任務地址,在運行結束后把等待執(zhí)行的任務的準備運行標志位置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++;

}

刪除任務

delete_task(局限性大,只針對當前運行的任務而言)

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(刪除指定任務名的任務)

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);
}

初始化任務空間

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é)點是沒有任務需要執(zhí)行的
	task_num=0;
}

調用實例

add_task(task1,500,RUN_NORMAL);//500ms執(zhí)行一次task1任務
add_wait_task(task1,task2,500);//task2等待task1結束才會執(zhí)行,運行的時間間隔為500ms
delete_task_withname(task1);//刪除task1任務

while(1){
    //...
    loop_task();//任務輪詢
}

結語

整體實現(xiàn)說難不難,說簡單不簡單,但也是我第一次嘗試這種偏向系統(tǒng)級應用的代碼,而且都沒有參照任何其他的資料和代碼,完全以自己的對任務的理解和具體項目的需求來一點點實現(xiàn),希望后面會把這個調度的代碼進一步完善成一個通用型的調度方式,也方便后面項目的使用了。

到此這篇關于利用C語言實現(xiàn)任務調度的示例代碼的文章就介紹到這了,更多相關C語言任務調度內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言非遞歸算法解決快速排序與歸并排序產生的棧溢出

    C語言非遞歸算法解決快速排序與歸并排序產生的棧溢出

    上期我們講完了排序算法下,不知道小伙伴們有沒有發(fā)現(xiàn)一個問題,快速排序和歸并排序我們都是用遞歸來實現(xiàn)的,可能有小伙伴會問,如果說數(shù)據(jù)量很多話,棧區(qū)空間會不會不夠用呢?這期我們就來解決使用遞歸實現(xiàn)的排序導致棧溢出如何解決
    2022-04-04
  • C++中Semaphore內核對象用法實例

    C++中Semaphore內核對象用法實例

    這篇文章主要介紹了C++中Semaphore內核對象用法實例,有助于深入了解信號量(Semaphore)的基本用法,需要的朋友可以參考下
    2014-10-10
  • Qt實現(xiàn)繪制網(wǎng)格背景的示例代碼

    Qt實現(xiàn)繪制網(wǎng)格背景的示例代碼

    這篇文章主要介紹了Qt如何實現(xiàn)繪制網(wǎng)格背景,并且能實現(xiàn)窗口大小調整時網(wǎng)格背景也自動調整重繪,感興趣的小伙伴可以跟隨小編一起學習一下
    2022-06-06
  • C/C++編程語言中的指針(pointer)你了解嗎

    C/C++編程語言中的指針(pointer)你了解嗎

    這篇文章主要為大家詳細介紹了C/C++編程語言中的指針,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C++隱式轉換問題分析及解決辦法

    C++隱式轉換問題分析及解決辦法

    在本篇文章里小編給大家整理了關于C++隱式轉換問題分析及解決辦法,有需要的朋友們可以學習下。
    2020-02-02
  • C和C++如何實現(xiàn)互相調用詳解

    C和C++如何實現(xiàn)互相調用詳解

    在學習c++中用到一些古老的c語言庫時,在工作中我們經常要使用C和C++混合編程,下面這篇文章主要給大家介紹了關于C和C++如何實現(xiàn)互相調用的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-01-01
  • C++函數(shù)重載介紹與原理詳解

    C++函數(shù)重載介紹與原理詳解

    這篇文章主要為大家介紹了C++函數(shù)重載介紹與原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • c文件匯編后函數(shù)參數(shù)傳遞的不同之處

    c文件匯編后函數(shù)參數(shù)傳遞的不同之處

    在w7 32位系統(tǒng)下把c文件匯編后,確實與mac后的差異很大??刹粌H僅是寄存器eax與rax的區(qū)別。我想說的是函數(shù)參數(shù)傳遞的不同
    2013-11-11
  • Qt教程之QSqlQueryModel的使用詳解

    Qt教程之QSqlQueryModel的使用詳解

    QSqlQueryModel是QSqlTableModel的父類,它封裝了執(zhí)行SELECT語句從數(shù)據(jù)庫查詢數(shù)據(jù)的功能,本文將為大家介紹一下QSqlQueryModel的使用,需要的可以參考一下
    2022-11-11
  • C++ map與set封裝實現(xiàn)過程講解

    C++ map與set封裝實現(xiàn)過程講解

    set set是一種關聯(lián)式容器,下面這篇文章主要給大家介紹了關于C++中map和set使用的相關資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用C++具有一定的參考學習價值,需要的朋友可以參考下
    2023-03-03

最新評論