linux 用戶空間電源管理 (二)

三.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_fdclient_fd數組相關,inotify_fdevdev_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超時時(修改serverclient共同訪問的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數組用於記錄bindserver 的所有socket,在廣播resumesuspend事件時,可以通過fd_client數組逐一發送信號給遠端地址,通知resumesuspend事件,而對於client端得socket_fd,只有一個,所以若發送失敗則關閉對應的遠端地址,從而只有最後一個註冊到client中的應用的socket能收到server的信息。

也就是說最後一個socket需要通知所有的遠端地址,已經收到resume或者suspend的通知,讓他們調用自己的回調函數。故涉及到遍歷通知信息的過程,所以設計註冊函數時,需要注意鏈表的使用。(事實上大多的註冊函數,多對一的情況下都需要考慮鏈表問題)

 

                                                               -- TO BE CONTINUED

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章