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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章