浅谈epoll的水平触发与边沿触发

概念

若监听的套接字描述符上有数据可读或可写,LT模式(水平触发)和ET模式(边沿触发)两种模式对应不同的通知模式。
        LT模式会不断的通知监听的套接字有数据可读或可写(对应套接字的读缓冲区不为空或写缓冲区不为满)
        ET模式只仅仅通知一次监听的套接字有数据可读或可写,除非缓冲区状态变化(读缓冲区由空变为非空,写缓冲区由满变为非满)才去通知相应事件。

几种IO复用模型对应的监听套接字的触发模型如下:

I/O模式 水平触发 边沿触发
select(), poll() 支持 不支持
信号驱动I/O 不支持 支持
epoll() 支持(默认) 支持

案例

学习了概念知识,接下来用一个案例进一步理解跟巩固所学概念,案例代码如下:

/**************************************
作   者 : lijd
生成日期 : 2021年02月04日
功能描述 : 测试epoll的水平触发和边沿触发
**************************************/ 
#include
#include
#include
#include
#include

int main(int argc, char *argv[])
{
    int iEpollType = 0;
    if(argc != 2)
    {
        perror("arg error! please cheak.");
        return -1;
    }
	
    0 == strcmp("LT", argv[1]) ? iEpollType = 1 : 0;
    0 == strcmp("ET", argv[1]) ? iEpollType = 2 : 0;
	
    if(iEpollType == 0)
    {
        perror("arg[1] error! is LT or ET.");
        return -1;
    }
    
    printf("iEpollType : %d\n", iEpollType);
		
    int fd[2];
    int ret = pipe(fd);
    if(ret == -1)
    {
        perror("pipe error");
        return 1;
    }
	
    pid_t id = fork();
    if(id == 0)	//child
    {
        close(fd[0]); // 关闭输出
        while(1)
        {
            char test[] = "aaaaaabbbbbb";		// 一次写入12个字符
            write(fd[1], test, strlen(test));
	    printf("child send:%s\n", test);
	    sleep(5);
	}
    }
    else if(id > 0)	//father
    {
	close(fd[1]);	 // 关闭输出
		
	struct epoll_event ev;
	struct epoll_event recvev[5];
	int i, res, len, efd;
	char buff[12] = {0};
		
	efd = epoll_create(5);
		
	iEpollType == 1 ? (ev.events = EPOLLIN) : (ev.events = EPOLLIN|EPOLLET);
	ev.data.fd = fd[0];
		
	epoll_ctl(efd, EPOLL_CTL_ADD, fd[0], &ev);
		
	while(1)
	{
	    res = epoll_wait(efd, recvev, 5, -1);
			
	    for(i = 0; i < res; i++)
	    {
		if(recvev[i].data.fd == fd[0])
		{
		    len = read(fd[0], buff, 6);	// 一次读6个字符
		    printf("father recv:%s\n", buff);
		}
	    }
	}
    }
    else
    {
	perror("fork error");
	return 2;
    }
    
    return 0;
}

程序执行结果如下:

浅谈epoll的水平触发与边沿触发_第1张图片

由上图程序执行结果让我们更进一步加强了对这两种触发模式的理解。根据上述的例子分析,LT模式:父进程每次收到子进程的数据时,它的套接字缓冲区中的数据通过epoll_wait()函数的2次触发而被读空;ET模式:父进程每次收到子进程的数据时,它的套接字缓冲区中的数据通过epoll_wait()函数的1次触发后读取部分数据,每次缓冲区中都有数据剩余。

你可能感兴趣的:(服务器,epoll,水平触发,边沿触发)