摘要: process_run用于處理系統(tǒng)所有needspoll標(biāo)記為1的進(jìn)程及處理事件隊列的下一個事件。本文深入原碼,詳細(xì)分析,也包括do_poll和do_event函數(shù)。
一、運(yùn)行process_run - int main()
-
{
-
dbg_setup_uart();
-
usart_puts("Initialising\n");
-
-
clock_init();
-
process_init();
-
process_start(&etimer_process, NULL);
-
autostart_start(autostart_processes);
-
-
while (1)
-
{
-
/*執(zhí)行完所有needspoll為1的進(jìn)程及處理完所有隊列*/
-
do
-
{
-
}
-
while (process_run() > 0);
-
}
-
return 0;
-
}
二、process_run剖析
process_run處理系統(tǒng)所有needspoll標(biāo)記為1的進(jìn)程及處理事件隊列的下一個事件,源代碼如下: - static volatile unsigned char poll_requested; //全局靜態(tài)變量,標(biāo)識系統(tǒng)是否有needspoll為1的進(jìn)程
-
-
int process_run(void)
-
{
-
if (poll_requested) //進(jìn)程鏈表有needspoll為1的進(jìn)程
-
{
-
do_poll(); //見2.1
-
}
-
-
do_event(); //見2.2
-
-
return nevents + poll_requested; //若和為1,則表示處理完系統(tǒng)的所有事件,并且沒有needspoll為1的進(jìn)程
-
}
透過上述的源代碼,可以直觀看出needspoll標(biāo)記為1的進(jìn)程可以優(yōu)先執(zhí)行。并且每執(zhí)行一次process_run,將處理系統(tǒng)所有needspoll標(biāo)記為1的進(jìn)程,而只處理事件隊列的一個事件。
2.1 do_poll函數(shù)
復(fù)位全局變量poll_requested,遍歷整個進(jìn)程鏈表,將needspoll標(biāo)記為1的進(jìn)程投入運(yùn)行,并將相應(yīng)的needspoll復(fù)位。源代碼如下: - static void do_poll(void)
-
{
-
struct process *p;
-
poll_requested = 0; //復(fù)位全局變量
-
-
for (p = process_list; p != NULL; p = p->next) //處理所有needspoll為1的進(jìn)程
-
{
-
if (p->needspoll) //將needspoll為1的進(jìn)程投入執(zhí)行
-
{
-
p->state = PROCESS_STATE_RUNNING;
-
p->needspoll = 0;
-
call_process(p, PROCESS_EVENT_POLL, NULL);
-
}
-
}
-
}
call_process函數(shù)剖析見博文《Contiki學(xué)習(xí)筆記:啟動一個進(jìn)程process_start 》第三部分。
2.2 do_event函數(shù)
do_event處理事件隊列的一個事件,有兩種事件需特殊處理:PROCESS_BROADCAST和PROCESS_EVENT_INIT。前者是廣播事件,需處理所有進(jìn)程,后者是初始化事件,需將進(jìn)程狀態(tài)設(shè)為PROCESS_STATE_RUNNING,以確保該進(jìn)程被進(jìn)程了。源代碼如下: - static process_num_events_t nevents; /*事件隊列的總事件數(shù) */
-
static process_num_events_t fevent; /*指向下一個要傳遞的事件的位置*/
-
static struct event_data events[PROCESS_CONF_NUMEVENTS]; /*事件隊列,用數(shù)組存儲,邏輯上是環(huán)形隊列*/
-
-
static void do_event(void)
-
{
-
/*以下3個變量恰為struct event_data的成員,用于暫存即將處理(fevent事件)的值*/
-
static process_event_t ev;
-
static process_data_t data;
-
static struct process *receiver;
-
-
static struct process *p;
-
-
if (nevents > 0)
-
{
-
/*提取將要處理事件的成員變量*/
-
ev = events[fevent].ev;
-
data = events[fevent].data;
-
receiver = events[fevent].p;
-
-
fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS; //更新fevent(指向下一個待處理的事件,類型于微機(jī)的PC)
-
--nevents; //事件隊列被組織成環(huán)形隊列,所以取余數(shù)
-
-
if (receiver == PROCESS_BROADCAST) //如果事件是廣播事件PROCESS_BROADCAST,則處理所有進(jìn)程
-
{
-
for (p = process_list; p != NULL; p = p->next)
-
{
-
if (poll_requested)
-
{
-
do_poll();
-
}
-
call_process(p, ev, data); //jelline note: call the receiver process twice??
-
}
-
}
-
else
-
{
-
if (ev == PROCESS_EVENT_INIT) //若事件是初始化,設(shè)置進(jìn)程狀態(tài),確保進(jìn)程狀態(tài)為PROCESS_STATE_RUNNING
-
{
-
receiver->state = PROCESS_STATE_RUNNING;
-
}
-
call_process(receiver, ev, data);
-
}
-
}
-
}
call_process函數(shù)剖析見博文《Contiki學(xué)習(xí)筆記:啟動一個進(jìn)程process_start 》第三部分。 |