天天看點

Posix标準中的timer和AIO

timer和aio這兩個東西都用到了linux的信号機制,而且根據初始化時的參數,庫或還提供了信号通知和回調函數通知兩種機制,所謂信号通知就是在 timer到期或者aio完成的時候發送信号給調用程序,而回調函數通知就是在timer到期或者aio完成時直接調用使用者注冊的回調函數,個人認為回調 函數要好一些,因為不用通過核心發送信号,但是信号更加統一,是标準的做法。核心實作提供了信号通知而沒有回調函數通知,畢竟linux并沒有實作"排程 激活"機制,另外核心實作為使用者提供了一個查詢接口,使用者可以随時查詢timer或者aio當時的狀态,查詢接口類似于輪詢,而通知類似于中斷。以下僅僅 讨論庫實作,關于核心實作可以參考我以前的文章或直接看核心。 

一.Posix timer 

不管是使用者空間的實作還是核心的實作,其基本原理都是一樣的,都符合posix的語義,所不同的就是效率問題和內建度的問題,比如核心沒有實作posix timer那麼使用者就必須要有posix的timer庫,僅此而已,寫到要用timer的使用者程式裡面實際是沒有任何差别的。timer的過程如下: 

1.準備參數,如果要信号通知的話必須首先确定timer到期後要發送給使用者的信号值,要用sigaction注冊一個信号處理函數, 如果用signal注冊的話,那麼siginfo參數資訊将丢失,或者不注冊任何處理函數,僅僅sleep/wakeup 

2.建立一個timer,并開啟一個線程專門負責這個timer的到期,删除,重置,該線程注冊了SIGALARM信号處理。 

3.timer到期以後2中建立的線程向使用者線程發送信号,信号的值就是1中使用者設定的參數,另外的參數就是siginfo, 也是由1中使用者設定的參數得到的,是否發送siginfo參數取決于核心是否實作帶siginfo參數的信号發送函數。 

4.使用者得到通知後可以取出siginfo裡面的參數,然後執行使用者自己定義的信号處理函數。 

注意:全過程中1中使用者設定的參數隻在庫即2中建立的線程向使用者程序發送信号的時候才進入核心。這和核心實作的是不同的。 

二.Posix AIO 

關于異步io,我前面好幾篇文章都談到了,隻不過那都是核心的實作,現在列出庫的實作。 

1.準備參數,大緻和上面的timer的過程1是一樣的。允許使用者設定兩種通知方式的一種,一個是信号通知,此情況下使用者必須提供信号處理函數,另一個是回調函數通知,此情況下使用者必須提供回調函數。 

2.觸發異步調用,使用者程序觸發了aio後立即傳回。 

3.aio函數調用堆棧立即進入aio庫,實際上就是建立一個新的線程,然後在此新線程執行同步io

4.3中的aio不一定就一個,是以必要的情況下會建立多個線程進行同步io,同一個線程的io操作串行排隊。 

5.當新線程的同步io結束以後根據使用者的參數,要麼向使用者發送一個信号,而使用者捕獲該信号後執行io完成操作,要麼再建立一個新線程,在該新線程裡面直接調用使用者的回調函數。在發送信号的時候,使用者的參數是否傳入依賴是否存在相關的系統調用,這個和timer一樣。 

總 結:以上簡單說了posix的timer和aio,當然還有線程接口也是很不錯的,不過線程接口很龐大,這裡就不分析了,要知道的是,完全實作posix 是個很艱巨的任務,即便linux也不是完全實作了posix的語義,也是修修補補的,典型的例子就是它的線程實作,NPTL之前的 linux_threads有着很多問題。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1273980

繼續閱讀