2012-01-01 56 views
4

如果我是epoll_wait()在一個監聽套接字上,並且當epoll_wait()返回時指示它有活動(在這種情況下,一個等待accept()的連接),那麼如果accept()調用失敗並且errno = EINTR,那麼epoll_wait()是否表示在下次返回時監聽套接字上的相同連接正在等待?accept()在信號中斷並且epoll_wait()

即,我需要做的線沿線的東西:

while(1){ 
    epoll_wait(epfd, &events, maxevents, timeout); 
    if (events.data.fd == listener){ 
     connsock = accept(listener, &addr, &addrlen); 
     while (connsock != -1){ 
      if (errno == EINTR){ 
       accept(listener, &addr, &addrlen); 
       } 
      } 
     } 
    } 

,以確保連接被接受,或將這項工作,仍然確保在其連接的accept()由信號中斷被接受:

while(1){ 
    epoll_wait(epfd, &events, maxevents, timeout); 
    if (events.data.fd == listener){ 
     connsock = accept(listener, &addr, &addrlen); 
     } 
    } 

其中在這種情況下,如果接受()是由一個信號,它會剛剛通過循環下一次拿起相同的連接epoll_wait再次返回之後中斷。顯然,在這兩個例子中,我做了一些假設(例如,在一個給定的epoll_wait調用中只返回一個套接字上的一個事件),並省略錯誤檢查(除accept()上的EINTR,因爲這是整點),以簡化事情

回答

2

這是邊緣觸發和電平觸發之間的區別。使用級別觸發,默認值,您不必擔心。

帶有觸發電平的折衷是,當另一個線程返回調用epoll_wait時,您不能讓一個線程處理檢測到的事件 - 它只會再次檢測到相同的事件。但在大多數情況下,無論如何你都不需要這樣做,而且不可能失去一個事件的權衡是值得的。

+0

反正你不會失去這個活動。直到掛起的連接被成功接受或超時爲止,它將保留在內核backlog中,並在下次輪詢時立即觸發epoll_wait。 – 2012-01-01 08:20:46

+2

@JasonCoco不處於邊緣觸發模式。邊緣觸發模式的要點是不讓一個線程處理事件,而另一個線程調用「epoll_wait」,並且如果沒有* new *事件,則阻塞。 (電平觸發是默認設置。)是否還可以通過EPOLLONESHOT選擇是否重新設置新事件。 – 2012-01-01 08:22:49

+0

謝謝,我很欣賞這種迴應。因此,水平觸發和邊緣觸發之間的差異可以被認爲是「處於某種狀態」和「自上次看上去以來已經改變到特定狀態」之間的區別?這是我通過閱讀手冊頁理解的,但我從未真正確認我的理解是正確的。 – 2012-01-02 19:40:04