程序架構(gòu)重要性
很多人尤其是初學(xué)者在寫代碼的時(shí)候往往都是想一點(diǎn)寫一點(diǎn),最開始沒有一個(gè)整體的規(guī)劃,導(dǎo)致后面代碼越寫越亂,bug不斷。
最終代碼跑起來看似沒有問題(有可能也真的沒有問題),但是系統(tǒng)的可擴(kuò)展性很差,添加一個(gè)功能的時(shí)候會(huì)浪費(fèi)大量的時(shí)間,甚至導(dǎo)致整個(gè)代碼的崩潰。
所以,在一個(gè)項(xiàng)目開始的時(shí)候多花一些時(shí)間在代碼的架構(gòu)設(shè)計(jì)上是十分有必要的。代碼架構(gòu)確定好了之后你會(huì)發(fā)現(xiàn)敲代碼的時(shí)候會(huì)特別快,并且在后期調(diào)試的時(shí)候也不會(huì)像無頭蒼蠅一樣胡亂找問題。當(dāng)然,調(diào)試也是一門技術(shù)。
在學(xué)習(xí)實(shí)時(shí)操作系統(tǒng)的過程中,發(fā)現(xiàn)實(shí)時(shí)操作系統(tǒng)框架與個(gè)人的業(yè)務(wù)代碼之間的耦合性就非常低,都是只需要將業(yè)務(wù)代碼通過一定的接口函數(shù)注冊(cè)好后就交給操作系統(tǒng)托管了,十分方便。
但是操作系統(tǒng)的調(diào)度過于復(fù)雜,這里就使用操作系統(tǒng)的思維方式來重構(gòu)這個(gè)時(shí)間片輪詢框架。實(shí)現(xiàn)該框架的完全解耦,用戶只需要包含頭文件,并且在使用過程中不需要改動(dòng)已經(jīng)寫好的庫文件。
Demo
首先來個(gè)demo,該demo是使用電腦開兩個(gè)線程:一個(gè)線程模擬單片機(jī)的定時(shí)器中斷產(chǎn)生時(shí)間片輪詢個(gè)時(shí)鐘,另一個(gè)線程則模擬主函數(shù)中一直運(yùn)行的時(shí)間片輪詢調(diào)度程序。
#include #include #include #include"timeslice.h" //創(chuàng)建5個(gè)任務(wù)對(duì)象 TimesilceTaskObjtask_1,task_2,task_3,task_4,task_5; //具體的任務(wù)函數(shù) voidtask1_hdl() { printf(">>task1isrunning...n"); } voidtask2_hdl() { printf(">>task2isrunning...n"); } voidtask3_hdl() { printf(">>task3isrunning...n"); } voidtask4_hdl() { printf(">>task4isrunning...n"); } voidtask5_hdl() { printf(">>task5isrunning...n"); } //初始化任務(wù)對(duì)象,并且將任務(wù)添加到時(shí)間片輪詢調(diào)度中 voidtask_init() { timeslice_task_init( task_1,task1_hdl,1,10); timeslice_task_init( task_2,task2_hdl,2,20); timeslice_task_init( task_3,task3_hdl,3,30); timeslice_task_init( task_4,task4_hdl,4,40); timeslice_task_init( task_5,task5_hdl,5,50); timeslice_task_add( task_1); timeslice_task_add( task_2); timeslice_task_add( task_3); timeslice_task_add( task_4); timeslice_task_add( task_5); } //開兩個(gè)線程模擬在單片機(jī)上的運(yùn)行過程 voidtimeslice_exec_thread() { while(true) { timeslice_exec(); } } voidtimeslice_tick_thread() { while(true) { timeslice_tick(); Sleep(10); } } intmain() { task_init(); printf(">>tasknum:%dn",timeslice_get_task_num()); printf(">>tasklen:%dn",timeslice_get_task_timeslice_len( task_3)); timeslice_task_del( task_2); printf(">>delettask2n"); printf(">>task2isexist:%dn",timeslice_task_isexist( task_2)); printf(">>tasknum:%dn",timeslice_get_task_num()); timeslice_task_del( task_5);printf(">>delettask5n"); printf(">>tasknum:%dn",timeslice_get_task_num()); printf(">>task3isexist:%dn",timeslice_task_isexist( task_3)); timeslice_task_add( task_2);printf(">>addtask2n"); printf(">>task2isexist:%dn",timeslice_task_isexist( task_2)); timeslice_task_add( task_5);printf(">>addtask5n"); printf(">>tasknum:%dn",timeslice_get_task_num()); printf("nn========timeslicerunning===========n"); std::threadthread_1(timeslice_exec_thread); std::threadthread_2(timeslice_tick_thread); thread_1.join(); thread_2.join(); return0; }
運(yùn)行結(jié)果如下:
由以上例子可見,這個(gè)框架使用十分方便,甚至可以完全不知道其原理,僅僅通過幾個(gè)簡單的接口就可以迅速創(chuàng)建任務(wù)并加入到時(shí)間片輪詢的框架中,十分好用。
時(shí)間片輪詢架構(gòu)
其實(shí)該部分主要使用了面向?qū)ο蟮乃季S,使用結(jié)構(gòu)體作為對(duì)象,并使用結(jié)構(gòu)體指針作為參數(shù)傳遞,這樣作可以節(jié)省資源,并且有著極高的運(yùn)行效率。
其中最難的部分是侵入式鏈表的使用,這種鏈表在一些操作系統(tǒng)內(nèi)核中使用十分廣泛,這里是參考RT-Thread實(shí)時(shí)操作系統(tǒng)中的侵入式鏈表實(shí)現(xiàn)。
h文件:
#ifndef_TIMESLICE_H #define_TIMESLICE_H #include"./list.h" typedefenum { TASK_STOP, TASK_RUN }IsTaskRun; typedefstructtimesilce { unsignedintid; void(*task_hdl)(void); IsTaskRunis_run; unsignedinttimer; unsignedinttimeslice_len; ListObjtimeslice_task_list; }TimesilceTaskObj; voidtimeslice_exec(void); voidtimeslice_tick(void); voidtimeslice_task_init(TimesilceTaskObj*obj,void(*task_hdl)(void),unsignedintid,unsignedinttimeslice_len); voidtimeslice_task_add(TimesilceTaskObj*obj); voidtimeslice_task_del(TimesilceTaskObj*obj); unsignedinttimeslice_get_task_timeslice_len(TimesilceTaskObj*obj); unsignedinttimeslice_get_task_num(void); unsignedchartimeslice_task_isexist(TimesilceTaskObj*obj); #endifc文件:
#include"./timeslice.h" staticLIST_HEAD(timeslice_task_list); voidtimeslice_exec() { ListObj*node; TimesilceTaskObj*task; list_for_each(node, timeslice_task_list) { task=list_entry(node,TimesilceTaskObj,timeslice_task_list); if(task->is_run==TASK_RUN) { task->task_hdl(); task->is_run=TASK_STOP; } } } voidtimeslice_tick() { ListObj*node; TimesilceTaskObj*task; list_for_each(node, timeslice_task_list) { task=list_entry(node,TimesilceTaskObj,timeslice_task_list); if(task->timer!=0) { task->timer--; if(task->timer==0) { task->is_run=TASK_RUN; task->timer=task->timeslice_len; } } } } unsignedinttimeslice_get_task_num() { returnlist_len( timeslice_task_list); } voidtimeslice_task_init(TimesilceTaskObj*obj,void(*task_hdl)(void),unsignedintid,unsignedinttimeslice_len) { obj->id=id; obj->is_run=TASK_STOP; obj->task_hdl=task_hdl; obj->timer=timeslice_len; obj->timeslice_len=timeslice_len; } voidtimeslice_task_add(TimesilceTaskObj*obj) { list_insert_before( timeslice_task_list, obj->timeslice_task_list); } voidtimeslice_task_del(TimesilceTaskObj*obj) { if(timeslice_task_isexist(obj)) list_remove( obj->timeslice_task_list); else return; } unsignedchartimeslice_task_isexist(TimesilceTaskObj*obj) { unsignedcharisexist=0; ListObj*node; TimesilceTaskObj*task; list_for_each(node, timeslice_task_list) { task=list_entry(node,TimesilceTaskObj,timeslice_task_list); if(obj->id==task->id) isexist=1; } returnisexist; } unsignedinttimeslice_get_task_timeslice_len(TimesilceTaskObj*obj) { returnobj->timeslice_len; }
底層侵入式雙向鏈表
該鏈表是linux內(nèi)核中使用十分廣泛,也十分經(jīng)典,其原理具體可以參考文章:
https://www.cnblogs.com/skywang12345/p/3562146.html
h文件:
#ifndef_LIST_H #define_LIST_H #defineoffset_of(type,member)(unsignedlong) ((type*)0)->member #definecontainer_of(ptr,type,member)((type*)((char*)(ptr)-offset_of(type,member))) typedefstructlist_structure { structlist_structure*next; structlist_structure*prev; }ListObj; #defineLIST_HEAD_INIT(name){ (name), (name)} #defineLIST_HEAD(name)ListObjname=LIST_HEAD_INIT(name) voidlist_init(ListObj*list); voidlist_insert_after(ListObj*list,ListObj*node); voidlist_insert_before(ListObj*list,ListObj*node); voidlist_remove(ListObj*node); intlist_isempty(constListObj*list); unsignedintlist_len(constListObj*list); #definelist_entry(node,type,member) container_of(node,type,member) #definelist_for_each(pos,head) for(pos=(head)->next;pos!=(head);pos=pos->next) #definelist_for_each_safe(pos,n,head) for(pos=(head)->next,n=pos->next;pos!=(head); pos=n,n=pos->next) #endif
c文件:
#include"list.h" voidlist_init(ListObj*list) { list->next=list->prev=list; } voidlist_insert_after(ListObj*list,ListObj*node) { list->next->prev=node; node->next=list->next; list->next=node; node->prev=list; } voidlist_insert_before(ListObj*list,ListObj*node) { list->prev->next=node; node->prev=list->prev; list->prev=node; node->next=list; } voidlist_remove(ListObj*node) { node->next->prev=node->prev; node->prev->next=node->next; node->next=node->prev=node; } intlist_isempty(constListObj*list) { returnlist->next==list; } unsignedintlist_len(constListObj*list) { unsignedintlen=0; constListObj*p=list; while(p->next!=list) { p=p->next; len++; } returnlen; }
到此,一個(gè)全新的,完全解耦的,十分方便易用時(shí)間片輪詢框架完成。
來源:小麥大叔
免責(zé)聲明:本文為轉(zhuǎn)載文章,轉(zhuǎn)載此文目的在于傳遞更多信息,版權(quán)歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權(quán)問題,請(qǐng)聯(lián)系小編進(jìn)行處理
審核編輯 黃宇
-
單片機(jī)
+關(guān)注
關(guān)注
6040文章
44594瀏覽量
636963 -
框架
+關(guān)注
關(guān)注
0文章
403瀏覽量
17515
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論