三.Server
Server本身維護一個定時器,當定時器超時,就讓系統進入節能模式。Server會接受其它進程的重置定時器的命令,阻止系統進入節能模式。
Server主要功能包括:
l 當定時器超時,讓系統進入節能模式。
l 接受來至其它進程的連接註冊(可能)。
l 接收來至其它進程的重置定時器命令。
l 接收來至其它進程的修改超時命令,維護超時時間在各個進程間同步。
l 通知其它進程系統準備進入節能模式和離開節能模式事件。
通過分析它的主要功能,我們可以設計如下的結構
在調用poll時,不僅包括上述的timer_fd,inotify_fd,socket_fd,reset_fd,還需要包括已註冊
的所有client_fd,需要監控的evdev_fd(這裏選擇監控input設備中的keyboard)。
而socket_fd與client_fd數組相關,inotify_fd與evdev_fd數組相關。
每當/dev/input/eventX有輸入時,則重置定製器。
在應用修改超時時間,事件需要廣播(其他應用和電源管理器都需要知道此事件),使用inotify機制,應用和管理器都監聽超時文件是否被修改,當發生修改之後,應用和管理器都重新讀取超時文件的內容,更新超時時間。
整個server端的設計是比較簡單的,就是全面的考慮電源管理所涉及的內容,然後對這些部分進行監控,如果有對應的事件就進行相應的處理,需要注意的是鎖的使用和對事件的清除操作(一般通過讀該文件清除)
思考:
1. 如何表明server已經運行? 通過一個lock文件來實現。當lock文件被鎖則
server在運行,如果lock文件未被鎖,則server未運行。
2. 對於server端,我們要考慮的問題就是定時器允許超時和不允許超時的情況,比
如在某些情況下是不允許進入睡眠模式的,這個時候需要通過client事件來實現。
對於系統休眠是所有註冊的client同意的情況下才進入睡眠模式的。如果一個client不同意則永遠不進入休眠。
設計一個定時器B(client端),區別於server的定時器A,運行定時器B和定時器A,當定時器B超時時(修改server和client共同訪問的reset文件,reset_fd),則重置定時器A,保證定時器A不超時,從而不進入休眠。這樣,我們把定時器A是否超時的控制權交給了client的定時器B,而定時器B是否超時(從而決定系統是否有可能進入休眠)由應用程序的狀態決定的。
如果應用程序不允許進入省電,則設置工作狀態爲work,這樣會啓動定時器B,保證不進入睡眠。如果所有關聯的應用程序均允許進入睡眠,則關閉定時器B,在滿足條件的情況下,可以進入休眠。
是否允許啓動定時器B,可以和思考1提到的部分一致,設置state文件,當該文件被鎖時,啓動定時器B,不允許進入休眠,否則反之。
四、client
1) 設計思路
對於上面提到的思考2,有了一個更清晰的認識,client端不僅僅是client的功能,還是一個庫的概念。註冊的應用程序通過調用client端提供的庫函數,來實現對定時器B的操作。
在client端,維護一個線程(如果server沒有運行,則這個線程也不運行)。
線程等待如下事件:
l 定時器B超時,將重置server端的定時器A,阻止系統進入節能模式。
l Server的定時器A超時時間被改變,將更新超時時間,如果當前狀態爲不允許進入休眠,還需要重啓client的定時器B。
l 應用調用Register函數和server建立起新連接,則開始監聽這個連接。
l Server通知用戶,準備進入節能模式和退出節能模式,調用相應的回調函數。
分析其功能,可以設置如下的結構,
整個client部分與server想關的功能還是比較簡單的,關鍵在於庫的註冊函數和一些與各個應用的接口。
思考:
在新的應用register時,我們會通過eventfd,即threadwakeupfd通知socket fd更新自己的socket_fd,從而保證client線程中的socket fd是與server socket通道相bind的最新的socket fd.
這樣就會存在一個問題,因爲在server中,我們有fd_client數組用於記錄bind到server 的所有socket,在廣播resume和suspend事件時,可以通過fd_client數組逐一發送信號給遠端地址,通知resume和suspend事件,而對於client端得socket_fd,只有一個,所以若發送失敗則關閉對應的遠端地址,從而只有最後一個註冊到client中的應用的socket能收到server的信息。
也就是說最後一個socket需要通知所有的遠端地址,已經收到resume或者suspend的通知,讓他們調用自己的回調函數。故涉及到遍歷通知信息的過程,所以設計註冊函數時,需要注意鏈表的使用。(事實上大多的註冊函數,多對一的情況下都需要考慮鏈表問題)
-- TO BE CONTINUED