epoll 水平觸發 邊緣觸發

2021-08-28 20:56:58 字數 2639 閱讀 3827

先簡單比較一下level trigger 和 edge trigger 模式的不同。

讓我們換乙個角度來理解et模式,事實上,epoll的et模式其實就是socket io完全狀態機。

當socket由不可讀變成可讀時,epoll的et模式返回read 事件。對於read 事件,開發者需要保證把讀取緩衝區資料全部讀出,man epoll可知:

示例**

需要讀者注意的是,socket模式是可寫的,因為傳送緩衝區初始時空的。故應用層有資料要傳送時,直接呼叫write系統呼叫傳送資料,若write系統呼叫返回ewouldblock則表示socket變為不可寫,或者write系統呼叫返回的數值小於傳入的buffer引數的大小,這時需要把未傳送的資料暫存在應用層待傳送列表中,等待epoll返回write事件,再繼續傳送應用層待傳送列表中的資料,同樣若應用層待傳送列表中的資料沒有一次性發完,那麼繼續等待epoll返回write事件,如此迴圈往復。所以可以反推得到如下結論,若應用層待傳送列表有資料,則該socket一定是不可寫狀態,那麼這時候要傳送新資料直接追加到待傳送列表中。若待傳送列表為空,則表示socket為可寫狀態,則可以直接呼叫write系統呼叫傳送資料。總結如下:

示例**:

void socket_impl_t::send_impl(const string& src_buff_)

//! socket buff is full, cache the data

if (false == m_send_buffer.empty())

string left_buff;

int ret = do_send(buff_, left_buff);

if (ret < 0)

else if (ret > 0)

else

}int socket_impl_t:: handle_epoll_write ()

doelse if (ret > 0)

else

} while (false == m_send_buffer.empty());

m_sc->handle_write_completed(this);

return 0;

}

lt模式主要是讀操作比較簡單,但是對於et模式並沒有優勢,因為將讀取緩衝區資料全部讀出並不是難事。而write操作,et模式則流程非常的清晰,按照完全狀態機來理解和實現就變得非常容易。而lt模式的write操作則複雜多了,要頻繁的維護epoll的wail列表。

在**編寫時,把epoll et當成狀態機,當socket被建立完成(accept和connect系統呼叫返回的socket)時加入到epoll列表,之後就不用在從中刪除了。為什麼呢?man epoll中的faq告訴我們,當socket被close掉後,其自動從epoll中刪除。對於監聽socket簡單說幾點注意事項:

示例**:

int acceptor_impl_t::handle_epoll_read()

else if (errno == eintr || errno == emfile || errno == econnaborted || errno == enfile ||

errno == eperm || errno == enobufs || errno == enomem)

perror("accept");

return -1;

}socket_i* socket = create_socket(new_fd);

socket->open();

} while (true);

return 0;

}

github :

ffrpc 介紹: 

對於監聽的socket檔案描述符我們用sockfd表示,對於accept()返回的檔案描述符(即要讀寫的檔案描述符)用connfd表示。

五.總結

1.對於監聽的sockfd,最好使用水平觸發模式,邊緣觸發模式會導致高併發情況下,有的客戶端會連線不上。如果非要使用邊緣觸發,網上有的方案是用while來迴圈accept()

2.對於讀寫的connfd,水平觸發模式下,阻塞和非阻塞效果都一樣,不過為了防止特殊情況,還是建議設定非阻塞。

3.對於讀寫的connfd,邊緣觸發模式下,必須使用非阻塞io,並要一次性全部讀寫完資料(用while來迴圈讀)。

參考c/servermode/epollserver.c中如何使用epoll進行

epoll 水平觸發 邊緣觸發

水平觸發 只要緩衝區還有資料,核心就還會通知使用者。使用者如果第一次讀取資料沒讀完,即使沒有任何新的操作觸發,還是可以繼續通過epoll wait來獲取事件 邊緣觸發 只有當新事件觸發的時候,才能通過epoll wait來獲取資料,如果第一次讀取資料沒讀完,就只能等待下一次事件觸發來獲取餘下的資料。...

epoll 水平觸發與邊緣觸發

epoll也是實現i o多路復用的一種方法,為了深入了解epoll的原理,我們先來看下epoll水平觸發 level trigger,lt,lt為epoll的預設工作模式 與邊緣觸發 edge trigger,et 兩種工作模式。使用脈衝訊號來解釋lt和et可能更加貼切。level是指訊號只需要處於...

epoll的水平觸發和邊緣觸發

即level triggered and edge triggered 簡單說來 level triggered 只要事件是處於就緒狀態,你每詢問一次,就告訴你一次它處於就緒狀態。edge triggered 只有在狀態改變的時候告訴你,這也是為什麼et模式下,建議用非阻塞的socket。下面我們來...