程序架構(gòu)重要性
很多人尤其是初學(xué)者在寫代碼的時候往往都是想一點寫一點,最開始沒有一個整體的規(guī)劃,導(dǎo)致后面代碼越寫越亂,bug不斷。 最終代碼跑起來看似沒有問題(有可能也真的沒有問題),但是要加一個功能的時候會浪費大量的時間,甚至導(dǎo)致整個代碼的崩潰。 所以,在一個項目開始的時候多花一些時間在代碼的架構(gòu)設(shè)計上是十分有必要的。代碼架構(gòu)確定好了之后你會發(fā)現(xiàn)敲代碼的時候會特別快,并且在后期調(diào)試的時候也不會像無頭蒼蠅一樣胡亂找問題。當(dāng)然,調(diào)試也是一門技術(shù)。 在學(xué)習(xí)實時操作系統(tǒng)的過程中,發(fā)現(xiàn)實時操作系統(tǒng)框架與個人的業(yè)務(wù)代碼之間的耦合性就非常低,都是只需要將業(yè)務(wù)代碼通過一定的接口函數(shù)注冊好后就交給操作系統(tǒng)托管了,十分方便。 但是操作系統(tǒng)的調(diào)度過于復(fù)雜,這里就使用操作系統(tǒng)的思維方式來重構(gòu)這個時間片輪詢框架。實現(xiàn)該框架的完全解耦,用戶只需要包含頭文件,并且在使用過程中不需要改動已經(jīng)寫好的庫文件。
Demo
首先來個demo,該demo是使用電腦開兩個線程:一個線程模擬單片機的定時器中斷產(chǎn)生時間片輪詢個時鐘,另一個線程則模擬主函數(shù)中一直運行的時間片輪詢調(diào)度程序。
#include運行結(jié)果如下:#include #include #include "timeslice.h" // 創(chuàng)建5個任務(wù)對象 TimesilceTaskObj task_1, task_2, task_3, task_4, task_5; // 具體的任務(wù)函數(shù) void task1_hdl() { printf(">> task 1 is running ... "); } void task2_hdl() { printf(">> task 2 is running ... "); } void task3_hdl() { printf(">> task 3 is running ... "); } void task4_hdl() { printf(">> task 4 is running ... "); } void task5_hdl() { printf(">> task 5 is running ... "); } // 初始化任務(wù)對象,并且將任務(wù)添加到時間片輪詢調(diào)度中 void task_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); } // 開兩個線程模擬在單片機上的運行過程 void timeslice_exec_thread() { while (true) { timeslice_exec(); } } void timeslice_tick_thread() { while (true) { timeslice_tick(); Sleep(10); } } int main() { task_init(); printf(">> task num: %d ", timeslice_get_task_num()); printf(">> task len: %d ", timeslice_get_task_timeslice_len(&task_3)); timeslice_task_del(&task_2); printf(">> delet task 2 "); printf(">> task 2 is exist: %d ", timeslice_task_isexist(&task_2)); printf(">> task num: %d ", timeslice_get_task_num()); timeslice_task_del(&task_5); printf(">> delet task 5 "); printf(">> task num: %d ", timeslice_get_task_num()); printf(">> task 3 is exist: %d ", timeslice_task_isexist(&task_3)); timeslice_task_add(&task_2); printf(">> add task 2 "); printf(">> task 2 is exist: %d ", timeslice_task_isexist(&task_2)); timeslice_task_add(&task_5); printf(">> add task 5 "); printf(">> task num: %d ", timeslice_get_task_num()); printf(" ========timeslice running=========== "); std::thread thread_1(timeslice_exec_thread); std::thread thread_2(timeslice_tick_thread); thread_1.join(); thread_2.join(); return 0; }

時間片輪詢架構(gòu)
其實該部分主要使用了面向?qū)ο蟮乃季S,使用結(jié)構(gòu)體作為對象,并使用結(jié)構(gòu)體指針作為參數(shù)傳遞,這樣作可以節(jié)省資源,并且有著極高的運行效率。 其中最難的部分是侵入式鏈表的使用,這種鏈表在一些操作系統(tǒng)內(nèi)核中使用十分廣泛,這里是參考RT-Thread實時操作系統(tǒng)中的侵入式鏈表實現(xiàn)。 h文件:
#ifndef _TIMESLICE_H
#define _TIMESLICE_H
#include "./list.h"
typedef enum {
TASK_STOP,
TASK_RUN
} IsTaskRun;
typedef struct timesilce
{
unsigned int id;
void (*task_hdl)(void);
IsTaskRun is_run;
unsigned int timer;
unsigned int timeslice_len;
ListObj timeslice_task_list;
} TimesilceTaskObj;
void timeslice_exec(void);
void timeslice_tick(void);
void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len);
void timeslice_task_add(TimesilceTaskObj* obj);
void timeslice_task_del(TimesilceTaskObj* obj);
unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj);
unsigned int timeslice_get_task_num(void);
unsigned char timeslice_task_isexist(TimesilceTaskObj* obj);
#endif
c文件:
#include "./timeslice.h"
static LIST_HEAD(timeslice_task_list);
void timeslice_exec()
{
ListObj* node;
TimesilceTaskObj* task;
list_for_each(node, ×lice_task_list)
{
task = list_entry(node, TimesilceTaskObj, timeslice_task_list);
if (task->is_run == TASK_RUN)
{
task->task_hdl();
task->is_run = TASK_STOP;
}
}
}
void timeslice_tick()
{
ListObj* node;
TimesilceTaskObj* task;
list_for_each(node, ×lice_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;
}
}
}
}
unsigned int timeslice_get_task_num()
{
return list_len(×lice_task_list);
}
void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len)
{
obj->id = id;
obj->is_run = TASK_STOP;
obj->task_hdl = task_hdl;
obj->timer = timeslice_len;
obj->timeslice_len = timeslice_len;
}
void timeslice_task_add(TimesilceTaskObj* obj)
{
list_insert_before(×lice_task_list, &obj->timeslice_task_list);
}
void timeslice_task_del(TimesilceTaskObj* obj)
{
if (timeslice_task_isexist(obj))
list_remove(&obj->timeslice_task_list);
else
return;
}
unsigned char timeslice_task_isexist(TimesilceTaskObj* obj)
{
unsigned char isexist = 0;
ListObj* node;
TimesilceTaskObj* task;
list_for_each(node, ×lice_task_list)
{
task = list_entry(node, TimesilceTaskObj, timeslice_task_list);
if (obj->id == task->id)
isexist = 1;
}
return isexist;
}
unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj)
{
return obj->timeslice_len;
}
底層侵入式雙向鏈表
該鏈表是linux內(nèi)核中使用十分廣泛,也十分經(jīng)典,其原理具體可以參考文章: https://www.cnblogs.com/skywang12345/p/3562146.html h文件:
#ifndef _LIST_H #define _LIST_H #define offset_of(type, member) (unsigned long) &((type*)0)->member #define container_of(ptr, type, member) ((type *)((char *)(ptr) - offset_of(type, member))) typedef struct list_structure { struct list_structure* next; struct list_structure* prev; } ListObj; #define LIST_HEAD_INIT(name) {&(name), &(name)} #define LIST_HEAD(name) ListObj name = LIST_HEAD_INIT(name) void list_init(ListObj* list); void list_insert_after(ListObj* list, ListObj* node); void list_insert_before(ListObj* list, ListObj* node); void list_remove(ListObj* node); int list_isempty(const ListObj* list); unsigned int list_len(const ListObj* list); #define list_entry(node, type, member) container_of(node, type, member) #define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) #define list_for_each_safe(pos, n, head) for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next) #endifc文件:
#include "list.h"
void list_init(ListObj* list)
{
list->next = list->prev = list;
}
void list_insert_after(ListObj* list, ListObj* node)
{
list->next->prev = node;
node->next = list->next;
list->next = node;
node->prev = list;
}
void list_insert_before(ListObj* list, ListObj* node)
{
list->prev->next = node;
node->prev = list->prev;
list->prev = node;
node->next = list;
}
void list_remove(ListObj* node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
node->next = node->prev = node;
}
int list_isempty(const ListObj* list)
{
return list->next == list;
}
unsigned int list_len(const ListObj* list)
{
unsigned int len = 0;
const ListObj* p = list;
while (p->next != list)
{
p = p->next;
len++;
}
return len;
}
到此,一個全新的,完全解耦的,十分方便易用時間片輪詢框架完成。
審核編輯:黃飛
-
單片機
+關(guān)注
關(guān)注
6074文章
45361瀏覽量
664402 -
定時器
+關(guān)注
關(guān)注
23文章
3361瀏覽量
121892 -
實時操作系統(tǒng)
+關(guān)注
關(guān)注
1文章
206瀏覽量
31828 -
軟件架構(gòu)
+關(guān)注
關(guān)注
0文章
64瀏覽量
10597
原文標(biāo)題:軟件架構(gòu)之時間輪片法
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
如何設(shè)計一種優(yōu)先級和時間片相結(jié)合的調(diào)度法?
單片機的程序架構(gòu)——時間片輪詢【學(xué)習(xí)筆記】精選資料分享
嵌入式單片機程序架構(gòu)之時間片輪詢法
單片機程序架構(gòu)之時間輪片法程序架構(gòu)重要性解析
基于μC/OS-II的時間片調(diào)度法設(shè)計方法
ARM架構(gòu)應(yīng)用實例02時間片輪詢
時間片調(diào)度法設(shè)計方案分析
單片機的時間片輪詢的思路介紹和架構(gòu)說明
單片機中的時間片輪詢法解析
單片機程序時間輪片法框架
單片機的程序架構(gòu)——時間片輪詢【學(xué)習(xí)筆記】
單片機應(yīng)用程序架構(gòu)-時間片輪詢法
單片機程序架構(gòu)—時間輪片法
單片機面向?qū)ο笏季S的架構(gòu):時間輪片法

軟件架構(gòu)之時間輪片法
評論