<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【SmartOS】輕量級多任務調度系統

      SmartOS是一個完全由新生命團隊設計的嵌入式操作系統,主要應用于智能家居、物聯網、工業自動化控制等領域。

      ARM Cortex-M系列微處理器幾乎全都做成單核心,對于業務邏輯較復雜的物聯網就顯得難以使用,因此SmartOS設計了兩個多任務調度系統:
      1,多線程調度,重量級,逼近PC操作系統多線程用法。使用上需要特別小心,要合理分配每一個線程的棧空間大小,任務越多越容易出問題
      2,大循環,輕量級。每個任務注冊一個函數指針,然后由主線程輪詢各個任務函數,輪流執行

      本文主要講解第二種,輕量級多任務調度系統。

      TaskScheduler是任務調度中心,Task表示單個任務。
      SmartOS啟動后會進入C/C++標準的main函數,在這里需要初始化各個模塊,各個模塊在初始化的時候,通過Sys.AddTask向系統注冊任務函數。
      一切就緒以后,在main最后一行,使用Sys.Start()進入大循環,開始調度。
      Sys.Start實際上調用
      TaskScheduler.Start,從后面代碼可以看出,這個Start內部有一個死循環。

      每一個任務都需要指定4大參數:函數指針、回調參數、開始時間、調度周期。
      調度中心將會維護并計算每一個任務的“下一次調度”時間。
      顯然,每一個任務函數獲得CPU時間開始執行的時候,其它所有任務都沒有機會執行。
      原則上,當然是每個任務都盡量不要占用太長的時間。但是隨著智能設備越來越復雜,應用系統也日漸復雜,為了滿足需求,開發人員很希望在一個任務里面完成一系列連貫動作,獲得跟PC上一樣的體驗,讓任務假設自己獨占CPU。
      常規的大循環調度根本無法滿足以上要求。

      我們在這個基礎上做了一點點改進,允許某個任務在休眠等待的時候,分出時間去調度其它函數。
      例如,A、B、C多個任務正在工作。
      其中A是主要業務邏輯,B是以太網驅動,定時詢問網卡要數據。
      A里面有一個功能,需要向服務器發送一個指令,然后等待響應。
      如果這個時候A阻塞CPU,它永遠也拿不到響應數據,即使響應數據已經到來!
      因為CPU被A獨占了,B沒有機會去問網卡要數據,也就不能把數據交給A。
      我們把A的等待做一點點調整,A在調用Sys.Sleep等待一定時間的時候,調度中心不要浪費了這點時間,安排去調度其它任務,那么B就有機會執行,網絡響應數據上冒到A業務附近的函數,最終被A獲取,達到業務需求。

      頭文件

       

      #ifndef __Task_H__
      #define __Task_H__
      
      #include "Sys.h"
      #include "List.h"
      
      class TaskScheduler;
      
      // 任務
      class Task
      {
      private:
              TaskScheduler* _Scheduler;
      
              friend class TaskScheduler;
      
              Task(TaskScheduler* scheduler);
      
      public:
              uint        ID;                        // 編號
              Action        Callback;        // 回調
              void*        Param;                // 參數
              long        Period;                // 周期us
              ulong        NextTime;        // 下一次執行時間
              uint        Times;                // 執行次數
              uint        CpuTime;        // 總耗費時間
              uint        SleepTime;        // 當前睡眠時間
              uint        Cost;                // 平均執行時間
              bool        Enable;                // 是否啟用
              byte        Reversed[3];// 保留,避免對齊問題
      
              //~Task();
      
              void ShowStatus();        // 顯示狀態
      };
      
      // 任務調度器
      class TaskScheduler
      {
      private:
              FixedArray<Task, 32> _Tasks;
              uint _gid;        // 總編號
      
              friend class Task;
      
      public:
              string        Name;                // 系統名稱
              int                Count;                // 任務個數
              Task*        Current;        // 正在執行的任務
              bool        Running;        // 是否正在運行
              byte        Reversed[3];// 保留,避免對齊問題
      
              TaskScheduler(string name = NULL);
              ~TaskScheduler();
      
              // 創建任務,返回任務編號。dueTime首次調度時間us,period調度間隔us,-1表示僅處理一次
              uint Add(Action func, void* param, ulong dueTime = 0, long period = 0);
              void Remove(uint taskid);
      
              void Start();
              void Stop();
              // 執行一次循環。指定最大可用時間
              void Execute(uint usMax);
      
              static void ShowStatus(void* param);        // 顯示狀態
      
          Task* operator[](int taskid);
      };
      
      #endif

       

      源代碼

      #include "Task.h"
      
      /*
      
      */
      
      Task::Task(TaskScheduler* scheduler)
      {
              _Scheduler = scheduler;
      
              Times                = 0;
              CpuTime                = 0;
              SleepTime        = 0;
              Cost                = 0;
              Enable                = true;
      }
      
      /*Task::~Task()
      {
              if(ID) _Scheduler->Remove(ID);
      }*/
      
      // 顯示狀態
      void Task::ShowStatus()
      {
              debug_printf("Task::Status 任務 %d [%d] 執行 %dus 平均 %dus\r\n", ID, Times, CpuTime, Cost);
      }
      
      TaskScheduler::TaskScheduler(string name)
      {
              Name = name;
      
              _gid = 1;
      
              Running = false;
              Current        = NULL;
              Count = 0;
      }
      
      TaskScheduler::~TaskScheduler()
      {
              Current = NULL;
              _Tasks.DeleteAll().Clear();
      }
      
      // 創建任務,返回任務編號。dueTime首次調度時間us,period調度間隔us,-1表示僅處理一次
      uint TaskScheduler::Add(Action func, void* param, ulong dueTime, long period)
      {
              Task* task = new Task(this);
              task->ID = _gid++;
              task->Callback = func;
              task->Param = param;
              task->Period = period;
              task->NextTime = Time.Current() + dueTime;
      
              Count++;
              _Tasks.Add(task);
      
      #if DEBUG
              // 輸出長整型%ld,無符號長整型%llu
              //debug_printf("%s添加任務%d 0x%08x FirstTime=%lluus Period=%ldus\r\n", Name, task->ID, func, dueTime, period);
              if(period >= 1000)
              {
                      uint dt = dueTime / 1000;
                      int  pd = period > 0 ? period / 1000 : period;
                      debug_printf("%s::添加任務%d 0x%08x FirstTime=%ums Period=%dms\r\n", Name, task->ID, func, dt, pd);
              }
              else
                      debug_printf("%s::添加任務%d 0x%08x FirstTime=%uus Period=%dus\r\n", Name, task->ID, func, (uint)dueTime, (int)period);
      #endif
      
              return task->ID;
      }
      
      void TaskScheduler::Remove(uint taskid)
      {
              int i = -1;
              while(_Tasks.MoveNext(i))
              {
                      Task* task = _Tasks[i];
                      if(task->ID == taskid)
                      {
                              _Tasks.RemoveAt(i);
                              debug_printf("%s::刪除任務%d 0x%08x\r\n", Name, task->ID, task->Callback);
                              // 首先清零ID,避免delete的時候再次刪除
                              task->ID = 0;
                              delete task;
                              break;
                      }
              }
      }
      
      void TaskScheduler::Start()
      {
              if(Running) return;
      
      #if DEBUG
              //Add(ShowTime, NULL, 2000000, 2000000);
              Add(ShowStatus, this, 10000000, 30000000);
      #endif
              debug_printf("%s::準備就緒 開始循環處理%d個任務!\r\n\r\n", Name, Count);
      
              Running = true;
              while(Running)
              {
                      Execute(0xFFFFFFFF);
              }
              debug_printf("%s停止調度,共有%d個任務!\r\n", Name, Count);
      }
      
      void TaskScheduler::Stop()
      {
              debug_printf("%s停止!\r\n", Name);
              Running = false;
      }
      
      // 執行一次循環。指定最大可用時間
      void TaskScheduler::Execute(uint usMax)
      {
              ulong now = Time.Current() - Sys.StartTime;        // 當前時間。減去系統啟動時間,避免修改系統時間后導致調度停擺
              ulong min = UInt64_Max;                // 最小時間,這個時間就會有任務到來
              ulong end = Time.Current() + usMax;
      
              // 需要跳過當前正在執行任務的調度
              //Task* _cur = Current;
      
              int i = -1;
              while(_Tasks.MoveNext(i))
              {
                      Task* task = _Tasks[i];
                      //if(task && task != _cur && task->Enable && task->NextTime <= now)
                      if(task && task->Enable && task->NextTime <= now)
                      {
                              // 不能通過累加的方式計算下一次時間,因為可能系統時間被調整
                              task->NextTime = now + task->Period;
                              if(task->NextTime < min) min = task->NextTime;
      
                              ulong now2 = Time.Current();
                              task->SleepTime = 0;
      
                              Current = task;
                              task->Callback(task->Param);
                              Current = NULL;
      
                              // 累加任務執行次數和時間
                              task->Times++;
                              int cost = (int)(Time.Current() - now2);
                              if(cost < 0) cost = -cost;
                              //if(cost > 0)
                              {
                                      task->CpuTime += cost - task->SleepTime;
                                      task->Cost = task->CpuTime / task->Times;
                              }
      
      #if DEBUG
                              if(cost > 500000) debug_printf("Task::Execute 任務 %d [%d] 執行時間過長 %dus 睡眠 %dus\r\n", task->ID, task->Times, cost, task->SleepTime);
      #endif
      
                              // 如果只是一次性任務,在這里清理
                              if(task->Period < 0) Remove(task->ID);
                      }
      
                      // 如果已經超出最大可用時間,則退出
                      if(!usMax || Time.Current() > end) return;
              }
      
              // 如果有最小時間,睡一會吧
              now = Time.Current();        // 當前時間
              if(min != UInt64_Max && min > now)
              {
                      min -= now;
      #if DEBUG
                      //debug_printf("TaskScheduler::Execute 等待下一次任務調度 %uus\r\n", (uint)min);
      #endif
                      //// 最大只允許睡眠1秒,避免Sys.Delay出現設計錯誤,同時也更人性化
                      //if(min > 1000000) min = 1000000;
                      //Sys.Delay(min);
                      Time.Sleep(min);
              }
      }
      
      // 顯示狀態
      void TaskScheduler::ShowStatus(void* param)
      {
              TaskScheduler* ts = (TaskScheduler*)param;
              
              int i = -1;
              while(ts->_Tasks.MoveNext(i))
              {
                      Task* task = ts->_Tasks[i];
                      if(task) task->ShowStatus();
              }
      }
      
      Task* TaskScheduler::operator[](int taskid)
      {
              int i = -1;
              while(_Tasks.MoveNext(i))
              {
                      Task* task = _Tasks[i];
                      if(task && task->ID == taskid) return task;
              }
      
              return NULL;
      }

      外部注冊函數

      // 任務
      #include "Task.h"
      // 任務類
      TaskScheduler* _Scheduler;
      
      // 創建任務,返回任務編號。priority優先級,dueTime首次調度時間us,period調度間隔us,-1表示僅處理一次
      uint TSys::AddTask(Action func, void* param, ulong dueTime, long period)
      {
              // 屏蔽中斷,否則可能有線程沖突
              SmartIRQ irq;
      
              if(!_Scheduler) _Scheduler = new TaskScheduler("系統");
      
              return _Scheduler->Add(func, param, dueTime, period);
      }
      
      void TSys::RemoveTask(uint taskid)
      {
              assert_ptr(_Scheduler);
      
              _Scheduler->Remove(taskid);
      }
      
      void TSys::SetTask(uint taskid, bool enable)
      {
              Task* task = (*_Scheduler)[taskid];
              if(task) task->Enable = enable;
      }
      
      void TSys::Start()
      {
              if(!_Scheduler) _Scheduler = new TaskScheduler("系統");
      
      #if DEBUG
              //AddTask(ShowTime, NULL, 2000000, 2000000);
      #endif
              if(OnStart)
                      OnStart();
              else
                      _Scheduler->Start();
      }
      
      void TSys::StartInternal()
      {
              _Scheduler->Start();
      }
      
      void TSys::Stop()
      {
              _Scheduler->Stop();
      }
      
      void TimeSleep(uint us)
      {
              // 在這段時間里面,去處理一下別的任務
              if(_Scheduler && (!us || us >= 1000))
              {
                      // 記錄當前正在執行任務
                      Task* task = _Scheduler->Current;
      
                      ulong start = Time.Current();
                      // 1ms一般不夠調度新任務,留給硬件等待
                      ulong end = start + us - 1000;
                      // 如果休眠時間足夠長,允許多次調度其它任務
                      int cost = 0;
                      while(true)
                      {
                              ulong start2 = Time.Current();
      
                              _Scheduler->Execute(us);
      
                              ulong now = Time.Current();
                              cost += (int)(now - start2);
      
                              // us=0 表示釋放一下CPU
                              if(!us) return;
      
                              if(now >= end) break;
                      }
      
                      if(task)
                      {
                              _Scheduler->Current = task;
                              task->SleepTime += cost;
                      }
      
                      cost = (int)(Time.Current() - start);
                      if(cost > 0) return;
      
                      us -= cost;
              }
              if(us) Time.Sleep(us);
      }
      
      void TSys::Sleep(uint ms)
      {
              // 優先使用線程級睡眠
              if(OnSleep)
                      OnSleep(ms);
              else
              {
      #if DEBUG
                      if(ms > 1000) debug_printf("Sys::Sleep 設計錯誤,睡眠%dms太長,超過1000ms建議使用多線程Thread!", ms);
      #endif
      
                      TimeSleep(ms * 1000);
              }
      }
      
      void TSys::Delay(uint us)
      {
              // 如果延遲微秒數太大,則使用線程級睡眠
              if(OnSleep && us >= 2000)
                      OnSleep((us + 500) / 1000);
              else
              {
      #if DEBUG
                      if(us > 1000000) debug_printf("Sys::Sleep 設計錯誤,睡眠%dus太長,超過1000ms建議使用多線程Thread!", us);
      #endif
      
                      TimeSleep(us);
              }
      }

       

      posted @ 2017-09-03 13:27  大石頭  閱讀(2543)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 99久久精品国产一区二区暴力| 国产美熟女乱又伦AV果冻传媒 | 成人免费在线播放av| 国产成人精品2021欧美日韩| 国产成人无码区免费内射一片色欲| 亚洲国产aⅴ成人精品无吗| 精品乱人码一区二区二区| 亚洲av无码之国产精品网址蜜芽| gogo无码大胆啪啪艺术| 一本久久a久久精品综合| 亚洲国产一区二区在线| 亚洲中文字幕无码日韩精品| 亚洲春色在线视频| 国产亚洲精品岁国产精品| 治县。| 亚洲国产一区二区三区四| 午夜福利国产精品视频| 欧美午夜成人片在线观看| 尤物蜜芽国产成人精品区| 亚洲精品久久久久国色天香| 成人欧美日韩一区二区三区| 色达县| 依依成人精品视频在线观看| 国产精品成人av电影不卡| 青青草原网站在线观看| 伊人久久大香线蕉综合观| 在线天堂www在线| 麻豆麻豆麻豆麻豆麻豆麻豆| 国产精品午夜福利精品| gogogo高清在线观看视频中文| 亚洲精品二区在线播放| 亚洲天堂网中文在线资源| 欧美一区二区三区欧美日韩亚洲| gogogo高清在线播放免费| 国产午夜三级一区二区三| 国产亚洲一区二区三区成人 | 亚洲av成人一区二区三区| 亚洲欧洲一区二区精品| 秋霞A级毛片在线看| 国产成人综合久久亚洲av| 999精品全免费观看视频|