2011-11-29 46 views
1

的應用程序需要能夠在各種情況設置回調基於時間的事件,子進程結束,數據。這些事件可以是任何的:等待抵達文件描述符

  • UTC時間已經達到

  • 數據已經到達的文件描述符

  • 子進程已經完成。

我需要編寫一個函數來分派事件。該應用程序將在嵌入式平臺上運行,並應採取合理步驟最大限度地降低CPU利用率。

一種方法將是一個繁忙的循環:

#define MAX_EVENT 10 

typedef enum tagEventType {EV_DATA, EV_CHILD, EV_TIME} tEventType; 
typedef void(*tEventCallback)(int); 
typedef struct tagEvent 
{ 
    int sequence; 
    tEventType type; 
    tEventCallback callback; 
    time_t time; 
    int fd; 
    pid_t pid;  
} tEvent; 

static tEvent eventsTable[MAX_EVENT];  

static void processEvents(void) 
{ 
    int i; 
    for (i=0; i<MAX_EVENT; ++i) 
    { 
     if (eventsTable[i].sequence > 0) 
     { 
      switch(eventsTable[i].type) 
      { 
       case EV_DATA: 
        if (checkForDataUsingPoll(eventsTable[i].fd)) 
        { 
         eventsTable[i].callback(eventsTable[i].sequence); 
        }      
        break; 
       case EV_CHILD: 
        if (kill(eventsTable[i].pid, 0) == -1) 
        { 
         eventsTable[i].callback(eventsTable[i].sequence); 
         eventsTable[i].sequence = 0;       
        } 
        break; 
       case EV_TIME: 
        { 
         if (time(NULL) > eventsTable[i].time) 
         { 
          eventsTable[i].callback(eventsTable[i].sequence); 
          eventsTable[i].sequence = 0; 
         } 
        } 
        break; 
      } 
     } 
    } 
} 

int main( int argc, char* argv[]) 
{ 
    signal(SIGCHLD, SIG_IGN); 
    while(1) 
    { 
     processEvents(); 
     usleep(1000); 
    } 
    return 0;  
} 

checkForDataUsingPoll()使用輪詢()具有零超時檢查數據是否已經到達的文件描述符。爲了簡潔,我省略了它。

是否有這樣做避免了繁忙的環路的一種方式?也許是輪詢,信號和警報的混合?

回答

1

對於文件描述符,有poll(您已經使用)或selectepoll或libevent。您還可以檢查SIGIO信號,或前綴aio_的功能。

對於時間,你可以檢查alarm系統調用。

子進程結束,檢查SIGCHLD信號。

編輯要回答評論:對於信號,您並不需要做任何事情,您設置的信號處理程序將在系統出現時自動調用。如果他們發生了一個標誌和可能的其他變量來通知你的程序發生了什麼。

當收到信號時,poll將返回一個錯誤,errno設置爲EINTR。如果是這種情況,請檢查信號處理程序設置的標誌以查看發生了什麼,並調用所需的任何功能。如果這是一個警報,那麼你必須重新啓動下一個事件的警報。然後再次撥打poll,等待下一個事件發生。

除非您有其他事情要做,否則您甚至可以撥打poll進行無限超時。它將返回信號或文件描述符準備就緒。

+0

我不清楚的是如何同時等待投票,SIGALRM和SIGCHLD。我猜poll()會被一個信號中斷。然後我不得不重新發出報警()爲下一個定時事件...... –

+0

@SimonElliott更新我的答案。 –

+0

謝謝。其實我不需要alarm(),因爲我只能使用poll()超時。 –