MTK task 簡單總結(jié)(速成版)_第1頁
MTK task 簡單總結(jié)(速成版)_第2頁
MTK task 簡單總結(jié)(速成版)_第3頁
MTK task 簡單總結(jié)(速成版)_第4頁
MTK task 簡單總結(jié)(速成版)_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、MTK task 小結(jié) 1MTK 的基本執(zhí)行單元是task,從操作系統(tǒng)的角度來理解,task 有些像線程而不是進(jìn)程,進(jìn)程之間的地址空間是相互隔離的,說白點(diǎn)就是進(jìn)程之間的全局變量是不相互干擾的。而線程之間則是用同一個地址空間,MTK的task之間的地址空間也是共同的,也就是說在MTK 編程里,定義了一個全局變量,那么在任何一個task里面都能引用,(這里只是舉個例子,在實(shí)際編程過程中最好不要用全局變量,實(shí)在沒有辦法避開,那么全局變量也要分模塊化,進(jìn)行封裝)。所以說,MTK 的task 更像線程,MTK 用的是實(shí)時操作系統(tǒng) nucleus,是非搶占式操作系統(tǒng),也就是當(dāng)高優(yōu)先級的task 在運(yùn)行時,

2、低優(yōu)先級的task是得不到運(yùn)行時間的,除非等高優(yōu)先級的task 因?yàn)榉N種原因掛起。MTK 還有一個跟task 想關(guān)的概念叫 module,它跟task 之間的關(guān)系是:一個task 可以對應(yīng)多個module。task 主要表示是一個執(zhí)行單元,module 主要是用于傳遞消息,在MTK 中,消息傳遞是module 為單位 src_mod > des_mod,而不是以task為單位。 MTK task 小結(jié) 2雖然MTK手機(jī),是feature phone(功能機(jī)),不像symbian 6 那樣可以同時運(yùn)行多個應(yīng)用。但是MTK還是由許多task組成。平時MTK的后臺播放MP3就是由一個task

3、完成的。具體以后分析。現(xiàn)在來看看MTK 最主要的task,MMI task,MTK的應(yīng)用程序都是在該task里面運(yùn)行,它有一整套開發(fā)MTK應(yīng)用的framework。先來看創(chuàng)建MMI task的函數(shù)kal_bool mmi_create(comptask_handler_struct *handle) /*-*/ /* Local Variables */ /*-*/ static comptask_handler_struct mmi_handler_info = MMI_task, /* task entry function */ MMI_Init, /* task initializat

4、ion function */ NULL, NULL, /* task reset handler */ NULL, /* task termination handler */ ; /*-*/ /* Code Body */ /*-*/ *handle = &mmi_handler_info; return KAL_TRUE;這個函數(shù)的結(jié)構(gòu),是MTK 創(chuàng)建task的基本結(jié)構(gòu),系統(tǒng)初始化時,會調(diào)用該函數(shù)。看里面的結(jié)構(gòu)體typedef struct kal_task_func_ptr comp_entry_func; /task 的入口函數(shù) task_init_func_ptr comp

5、_init_func; /task 的初始化函數(shù) task_cfg_func_ptr comp_cfg_func; /task 的配置函數(shù) task_reset_func_ptr comp_reset_func; /task 的重置函數(shù) task_end_func_ptr comp_end_func; /task 的終止函數(shù) comptask_handler_struct;task 的入口函數(shù)是必須的,這個函數(shù)告訴系統(tǒng),初始化完相應(yīng)的task 控制塊后,就要進(jìn)入該函數(shù)來運(yùn)行。task 初始化函數(shù),是在進(jìn)入 task 入口函數(shù)之前被調(diào)用,用來初始化可能需要的資源,可選。task 終止函數(shù)是,當(dāng)t

6、ask 結(jié)束是要調(diào)用,用來釋放資源,可選。其他兩個函數(shù)我也不清楚干什么,希望知道的共享下 先看MMI task 的初始化函數(shù).MMI_BOOL MMI_Init(task_indx_type task_indx) /創(chuàng)建一個mutex(互斥體) mmi_mutex_trace = kal_create_mutex("mmi_trace"); /這個是初始化 2step 按鍵, 2step 按鍵是指 有一些按鍵具有半按下狀態(tài) /比如照相功能,按下一半進(jìn)行聚焦,再按下一半拍照 mmi_frm_get_2step_keys();/初始化timer。L4InitTimer(); /

7、初始化 UI 相關(guān)信息,里面有許多畫點(diǎn),圖等函數(shù) setup_UI_wrappers(); return MMI_TRUE;初始化函數(shù)比較簡單。下面來看MMI 的入口函數(shù),這個函數(shù)是整個MMI 運(yùn)行的核心。/為了簡單,刪除了大部分宏控制程序void MMI_task(oslEntryType *entry_param) MYQUEUE Message; oslMsgqid qid; U32 my_index; U32 count = 0; U32 queue_node_number = 0; / 獲得task的外部消息隊(duì)列id,通過這個id,獲得別的task 往MMI task發(fā)送的消息 /

8、MMI task 有兩個消息,外部消息隊(duì)列和內(nèi)部消息隊(duì)列 / 外部消息隊(duì)列的消息不直接處理,只是簡單的存放到內(nèi)部消息隊(duì)列, / 這樣使內(nèi)部消息隊(duì)列的優(yōu)先級稍微高一點(diǎn) qid = task_info_gentry_param->task_indx.task_ext_qid; mmi_ext_qid = qid; / 初始化 event 處理函數(shù),這個幾個event 必須在獲得消息前就進(jìn)行注冊 / 不然可能使得這個event 丟棄。具體event 事件,下次介紹 InitEventHandlersBeforePowerOn(); /進(jìn)入task 的while 循環(huán) / task 的while

9、(1) 循環(huán)使得這個task 不會結(jié)束,只有掛起或者運(yùn)行 while (1) / 判斷是否有 key 事件需要處理 if (g_keypad_flag = MMI_TRUE) mmi_frm_key_handle(NULL); / 獲得外部消息隊(duì)列里,消息的個數(shù) msg_get_ext_queue_info(mmi_ext_qid, &queue_node_number); / 如果沒有任何消息需要處理(內(nèi)部消息和外部消息都沒有,同時也沒有按鍵需要處理) / OslNumOfCircularQMsgs 獲得內(nèi)部消息隊(duì)列消息的個數(shù) if (queue_node_number = 0) &

10、amp;& (OslNumOfCircularQMsgs() = 0) && (g_keypad_flag = MMI_FALSE) U8 flag = 0; ilm_struct ilm_ptr; /去外部消息隊(duì)列里獲得消息,這是一個阻塞函數(shù),也就是說,如果外部消息隊(duì)列里, /沒有任何消息,那么這個task 將被阻塞,或者說掛起,也就是不在運(yùn)行, /直到有消息到達(dá),才會被喚醒, 看過操作系統(tǒng)原理的,應(yīng)該不難理解這個意思和這個本質(zhì) OslReceiveMsgExtQ(qid, &Message); /如果有消息,獲得task 的index OslGetMyTas

11、kIndex(&my_index); / 設(shè)置該task的獲得mod 為MMI mod. OslStackSetActiveModuleID(my_index, MOD_MMI); /保存該消息,用于放入到內(nèi)部隊(duì)列 ilm_ptr.src_mod_id = Message.src_mod_id; ilm_ptr.dest_mod_id = Message.dest_mod_id; ilm_ptr.msg_id = Message.msg_id; ilm_ptr.sap_id = Message.sap_id; ilm_ptr.local_para_ptr = Message.local

12、_para_ptr; ilm_ptr.peer_buff_ptr = Message.peer_buff_ptr; /放入內(nèi)部隊(duì)列 / 這個內(nèi)部隊(duì)列是個簡單的循環(huán)隊(duì)列 flag = OslWriteCircularQ(&ilm_ptr); / 對 timer 消息進(jìn)行特殊處理 if (Message.src_mod_id != MOD_TIMER) hold_local_para(ilm_ptr.local_para_ptr); hold_peer_buff(ilm_ptr.peer_buff_ptr); OslFreeInterTaskMsg(&Message); else

13、/ 把外部消息放入到內(nèi)部消息 mmi_frm_fetch_msg_from_extQ_to_circularQ(); /處理內(nèi)部消息 count = OslNumOfCircularQMsgs(); while (count > 0) OslGetMyTaskIndex(&my_index); OslStackSetActiveModuleID(my_index, MOD_MMI); if (OslReadCircularQ(&Message) CheckAndPrintMsgId(U16) (Message.msg_id); /是否是 wap 的消息 / 這里就體現(xiàn)了一

14、個task 可以對應(yīng)多個mod if (Message.dest_mod_id = MOD_WAP) else switch (Message.msg_id) /timer消息 具體看 MTK timer 小結(jié) 2 case MSG_ID_TIMER_EXPIRY: kal_uint16 msg_len; /處理stack timer消息 EvshedMMITimerHandler(get_local_para_ptr(Message.oslDataPtr, &msg_len); break; /開機(jī)消息 /具體分析 見后文 case MSG_ID_MMI_EQ_POWER_ON_IN

15、D: mmi_eq_power_on_ind_struct *p = (mmi_eq_power_on_ind_struct*) Message.oslDataPtr; /* To initialize data/time */ SetDateTime(void*)&(p->rtc_time); gdi_init(); g_pwr_context.PowerOnMMIStatus = MMI_POWER_ON_INDICATION; switch (p->poweron_mode) case POWER_ON_KEYPAD: OslMemoryStart(MMI_TRUE)

16、; g_charbat_context.PowerOnCharger = 0; g_pwr_context.PowerOnMode = POWER_ON_KEYPAD; DTGetRTCTime(&StartUpTime); memset(&LastDuration, 0, sizeof(LastDuration); mmi_bootup_entry_disk_check(); break; case POWER_ON_PRECHARGE: case POWER_ON_CHARGER_IN: g_pwr_context.PowerOnMode = p->poweron_m

17、ode; InitializeChargingScr(); if (!g_charbat_context.isChargerConnected) QuitSystemOperation(); break; case POWER_ON_ALARM: g_pwr_context.PowerOnMode = POWER_ON_ALARM; gdi_layer_clear(GDI_COLOR_BLACK); AlmInitRTCPwron(); break; case POWER_ON_EXCEPTION: g_pwr_context.PowerOnMode = POWER_ON_EXCEPTION;

18、 gdi_layer_clear(GDI_COLOR_BLACK); OslMemoryStart(MMI_TRUE); SetAbnormalReset(); InitializeAll(); OslDumpDataInFile(); ClearInputEventHandler(MMI_DEVICE_ALL); ClearKeyHandler(KEY_END, KEY_LONG_PRESS);InitNvramData(); InitAllApplications(); mmi_pwron_exception_check_display();break; default: break; b

19、reak; / event 時間,這個也是MMI task 的一個重點(diǎn) default: ProtocolEventHandler( (U16) Message.oslMsgId, (void*)Message.oslDataPtr, (int)Message.oslSrcId, (void*)&Message); break; OslFreeInterTaskMsg(&Message); msg_get_ext_queue_info(mmi_ext_qid, &queue_node_number); count-; MMI task 內(nèi)容比較多,刪除了一些代碼,留下主

20、要的骨干。總體來看,1 把外部消息放入內(nèi)部消息隊(duì)列 2 處理各種消息,開機(jī)消息,按鍵消息 和event 機(jī)制注冊的各種其他消息MTK task 小結(jié) 3在 MTK task 小結(jié) 2 中 大概描述了下 MMI task 的工作方式:從外部隊(duì)列獲取消息放入內(nèi)部消息隊(duì)列,內(nèi)部消息隊(duì)列根據(jù)消息類型注冊的回調(diào)函數(shù),進(jìn)行調(diào)用(event 機(jī)制,這個又是MMI framework的主要部分之一)。在MTK上,用戶(開發(fā)人員)可以根據(jù)需要,創(chuàng)建task。創(chuàng)建一個task 分為 4 步:1 增加一個task index 到 custom_task_indx_type 2 增加一個mod index 到 cus

21、tom_module_type3 把mod 關(guān)聯(lián)到 相應(yīng)的 task上,因?yàn)橐粋€task 可以對應(yīng)多個mod,所以需要把mod 掛載到 task上。(用掛載這個詞,應(yīng)該就比較好理解了,task 是MTK 執(zhí)行的基本單位,所以一個mod 要能獨(dú)立運(yùn)行,就要掛載到某個task 上,為什么不一個mod一個task呢,我想task越多,多系統(tǒng)效率影響就越大。那么就可以考慮互斥的mod 掛載到一個task上,反正互斥的,不會同時需要運(yùn)行,就像音樂,視頻,照相機(jī)一樣,不會同時運(yùn)行)4 創(chuàng)建 task 基本信息 到 custom_comp_config_tbl下面來具體看一個例子。1 添加 task ind

22、ex typedef enum INDX_CUSTOM1 = RPS_CUSTOM_TASKS_BEGIN, INDX_CUSTOM2,#ifdef TASK_CREATE_TEST INDX_TASK_TEST,#endif RPS_CUSTOM_TASKS_END custom_task_indx_type;我們增加了一個 task index INDX_TASK_TEST2 添加一個 mod indextypedef enum MOD_CUSTOM1 = MOD_CUSTOM_BEGIN, MOD_CUSTOM2,#ifdef TASK_CREATE_TEST MOD_TASK_TEST

23、,#endif MOD_CUSTOM_END custom_module_type;我們增加了一個mod index MOD_TASK_TEST3 掛載mod 到 task上custom_task_indx_type custom_mod_task_g MAX_CUSTOM_MODS = INDX_CUSTOM1, /* MOD_CUSTOM1 */ INDX_CUSTOM2, /* MOD_CUSTOM2 */#ifdef TASK_CREATE_TEST INDX_TASK_TEST,#endif INDX_NIL /* Please end with INDX_NIL element *

24、/;這樣就把 MOD_TASK_TEST 掛載到 INDX_TASK_TEST上面了,這里的映射關(guān)系是通過index 來控制的,也就是說要的到MOD_TASK_TEST 對應(yīng)的 task index,只要這樣 task index = custom_mod_task_gMOD_TASK_TEST; 所以創(chuàng)建過程中,順序一定要對應(yīng)好,不然容易出錯。4 創(chuàng)建task 信息const comptask_info_struct custom_comp_config_tbl MAX_CUSTOM_TASKS = /* INDX_CUSTOM1 */ "CUST1", "CU

25、ST1 Q", 210, 1024, 10, 0, #ifdef CUSTOM1_EXIST custom1_create, KAL_FALSE#else NULL, KAL_FALSE#endif , /* INDX_CUSTOM2 */ "CUST2", "CUST2 Q", 211, 1024, 10, 0, #ifdef CUSTOM2_EXIST custom2_create, KAL_FALSE#else NULL, KAL_FALSE#endif ,#ifdef TASK_CREATE_TEST /* INDX_TASK_TEST

26、 */ "TAST_TEST", "TASK_TEST Q", 212, 1024, 10, 0, task_test_create, KAL_FALSE ,#endif;這樣就創(chuàng)建好了task 的信息,這里說task 需要的信息typedef struct kal_char *comp_name_ptr; /task 的name kal_char *comp_qname_ptr; /外部隊(duì)列name kal_uint32 comp_priority; /優(yōu)先級 kal_uint16 comp_stack_size; /stack 大小 kal_uint

27、8 comp_ext_qsize; /外部隊(duì)列大小 kal_uint8 comp_int_qsize; /內(nèi)部隊(duì)列大小 kal_create_func_ptr comp_create_func; /task 創(chuàng)建函數(shù) kal_bool comp_internal_ram_stack; /是否是internal_ram_stack comptask_info_struct;task 的優(yōu)先級是數(shù)值越大,優(yōu)先級越低。由于是MTK 用的是實(shí)時操作系統(tǒng),高優(yōu)先級的task 只要需要,就會先運(yùn)行,一直運(yùn)行,所以task的優(yōu)先級定義時需要考慮清楚。comp_internal_ram_stack 表示是否使

28、用internal ram stack,internal ram 相對速度要快,但是數(shù)量很有限,一般自己創(chuàng)建的不要去使用,容易引起問題。MTK task 小結(jié) 4在 MTK task 小結(jié) 3 中寫到創(chuàng)建一個MTK task,沒有寫完,今天把剩下的寫完。下面需要介紹 創(chuàng)建task 信息的函數(shù)。kal_bool task_test_create(comptask_handler_struct *handle) static const comptask_handler_struct task_test_handler_info = task_test_main, /* task entry fu

29、nction */ NULL, /* task initialization function */ NULL, /* task configuration function */ NULL, /* task reset handler */ NULL, /* task termination handler */ ; *handle = (comptask_handler_struct *)&task_test_handler_info; return KAL_TRUE;這個函數(shù)的結(jié)構(gòu)是不是很眼熟,對,就是 MTK task 小結(jié) 2 介紹MMI task 創(chuàng)建函數(shù) mmi_crea

30、te,創(chuàng)建函數(shù)的格式都是一樣的,具體結(jié)構(gòu)體的說明就看 MTK task 小結(jié) 2 ,相應(yīng)的函數(shù)可以補(bǔ)充,簡單期間就有一個入口函數(shù),不過一般都夠了。void task_test_main(task_entry_struct * task_entry_ptr) / 消息實(shí)體 ilm_struct current_ilm; /消息隊(duì)列id oslMsgqid qid = task_info_gtask_entry_ptr->task_indx.task_ext_qid; /初始化一些信息,這里只會被執(zhí)行一次 tast_test_init() / 進(jìn)入消息循環(huán) while ( 1 ) /接受消息

31、,如果沒有消息,掛起該 task receive_msg_ext_q(qid , &current_ilm); /根據(jù)消息 id 處理各種消息 switch (current_ilm.msg_id) case MSG_ID_TASK_TEST_XX: break; default: break; free_ilm(&current_ilm); 這樣,一個task 就建立完成了。 如果想給自己的task 建立一個強(qiáng)大的 timer 功能,那么就可以根據(jù) MTK timer 小結(jié) 3 里介紹的那樣,建立一個event scheduler timer,注意,這個stack timer

32、 里的mod 要寫成MOD_TASK_TEST 而不是 MOD_MMI,這樣 MSG_ID_TIMER_EXPIRY 就會發(fā)送到這個task里面,只要進(jìn)行相應(yīng)的處理就ok了。task 之間的交互是通過消息來傳遞的,當(dāng)然也可以通過全局變量,共享內(nèi)存等等(這里不是linux 那樣的共享內(nèi)存,因?yàn)镸TK 里面,整個系統(tǒng)的地址空間只有一個,那么一個task里的內(nèi)存,可以被另一個task訪問,只要知道地址,沒有限制,具體可以看 MTK 內(nèi)存管理簡單總結(jié))。只要自己控制好(互斥問題),還是比較靈活的。比如想要在這個task 里面處理按鍵事件,比較繁瑣,先要在MMI task里面接受按鍵事件,然后根據(jù)自己定

33、義的消息,把這個按鍵事件發(fā)送到這個task里面,這個task里面根據(jù)相應(yīng)的消息處理函數(shù),分發(fā)處理。一般來說,task 做一些后臺處理比較方便(跟io有關(guān)的),如果想實(shí)現(xiàn)并行(linux時間片那樣系統(tǒng)自動切換task),那是不現(xiàn)實(shí),因?yàn)檫@個不是搶占式系統(tǒng),優(yōu)先級高task的除非自己掛起,否則會一直運(yùn)行。雖然說如果兩個task 如果優(yōu)先級一樣,或進(jìn)行輪詢,但是我自己試了,沒有實(shí)現(xiàn),不知道是否是當(dāng)時沒有用對。如果有實(shí)現(xiàn)的童鞋一定要告訴我, MTK task 小結(jié) 5 (TASK之間的消息機(jī)制)今天繼續(xù)昨天的,說一下task之間的消息發(fā)送。task 之間發(fā)送消息,第一是要添加一個消息 id,在cust

34、om_sap.h里面,/* Add customization message id here */MSG_ID_CUSTOM1_CUSTOM2 = CUSTOM_MSG_CODE_BEGIN,MSG_ID_CUSTOM2_CUSTOM1,MSG_ID_MSG_TEST, /添加了一個消息id接下來是發(fā)送MTK 發(fā)送消息是mod 到 mod,因?yàn)閙od是掛載到task上,那么最終還是發(fā)送到task上。MTK 發(fā)送消息是有一套固定的接口,對消息實(shí)體也有固定要求。消息的主體是 ilm_struct 結(jié)構(gòu):typedef struct ilm_struct module_type src_mod_i

35、d; /源 mod id module_type dest_mod_id; /目的 mod id sap_type sap_id; / Service Access Pointer Identifier 不清楚干什么用的 msg_type msg_id; / 消息 id 就是上面創(chuàng)建的MSG_ID_MSG_TEST local_para_struct *local_para_ptr; /消息信息載體 1 peer_buff_struct *peer_buff_ptr; /消息信息載體 2 ilm_struct;這個消息結(jié)構(gòu)不是隨便malloc 出來的,是由專門的函數(shù) allocate_ilm

36、來創(chuàng)建,這個函數(shù)會從一個pool 去申請,這樣做可以方便控制,同時也可以減少內(nèi)存分配釋放操作,碎片的產(chǎn)生。創(chuàng)建完畢后,可以填完剩下的信息, 注意 allocate_ilm 參數(shù)是當(dāng)前要發(fā)送消息的mod id,不要搞錯了。比如:ilm_struct *ilm_ptr = allocate_ilm(MOD_TASK_TEST); /創(chuàng)建一個消息結(jié)構(gòu)ilm_ptr->src_mod_id = MOD_TASK_TEST; /設(shè)定源mod idilm_ptr->dest_mod_id = MOD_MMI; /設(shè)定目的mod idilm_ptr->sap_id = 0;ilm_ptr->msg_id = (msg_type) MSG_ID_MSG_TEST; /設(shè)定消息id接著需要一個消息 實(shí)體,也就是搭載具體消息信息的結(jié)構(gòu)體typedef struct local_para_struct LOCAL_PARA_HDR local_para_struct;其實(shí)這個結(jié)構(gòu)體只有一個頭信息 #define LOCAL_PARA_HDR kal_uint8ref_count; kal_uint16msg_len;分別用來記錄該信息的引用

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論