epoll水平觸發與邊緣觸發

把高電平看作文件描述符是可讀或可寫狀態,低電平黑色表示不可讀或不可寫,epoll_wait的水平觸發就是藍色的時候epoll_wait就會被觸發,而邊緣觸發就是紅色的時候epoll_wait會觸發,且只會觸發一次。比如,client_fd在某時刻充入數據,epoll_wait第一次檢測到,水平、邊緣都會觸發,進程開始讀數據,若數據沒有讀完。那麼水平觸發會在下一次運行到epoll_wait的時候再觸發一次,而邊緣觸發就不會。

​ 水平觸發下,可能會多次調用epoll_wait導致效率低下。而邊緣觸發下,如果第一次觸發沒有讀乾淨緩衝區,那麼就只能等到下一次衝入數據才能觸發epoll_wait讀出上一次的數據,所以在邊緣觸發下,必須一次將緩衝區的數據讀乾淨。

​ 方法就是在死循環裏一直讀client_fd,但讀完後read系統調用會阻塞,所以要將client_fd設置爲非阻塞:

int flags = fcntl(client_fd, F_GETFL);//獲取的cfd的標誌位
flags |= O_NONBLOCK;
fcntl(client_fd,F_SETFL,flags);

​ 當read讀非阻塞文件描述符讀乾淨的時候,不會阻塞,而是返回-1並且把errno設置爲EAGAIN,這時就可以跳出死循環。

while (1)
{
    char buf[SIZE] = "";
    int n = read(fd, buf, SIZE);

    if (n < 0)
    {
        if (errno == EAGAIN)
        {
            printf("讀完了\n");
            break;
        }

        Close(fd);
        epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
        perror("read");
        return 1;
    }
    else if (0 == n) // 套接字關閉
    {
        printf("client close\n");
        Close(fd);
        epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
        break;
    }
    else
    {
        Write(STDOUT_FILENO, buf, SIZE);
        Write(fd, buf, n);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章