- LT 模式下,读事件触发后,可以按需收取想要的字节数,不用把本次接收到的数据收取干净(即不用循环到 recv 或者 read 函数返回 -1,错误码为 EWOULDBLOCK 或 EAGAIN);ET 模式下,读事件必须把数据收取干净,因为你不一定有下一次机会再收取数据了,即使有机会,也可能存在上次没读完的数据没有及时处理,造成客户端响应延迟。
- LT 模式下,不需要写事件一定要及时移除,避免不必要的触发,浪费 CPU 资源;ET 模式下,写事件触发后,如果还需要下一次的写事件触发来驱动任务(例如发上次剩余的数据),你需要继续注册一次检测可写事件。
- LT 模式和 ET 模式各有优缺点,无所谓孰优孰劣。使用 LT 模式,我们可以自由决定每次收取多少字节(对于普通 socket)或何时接收连接(对于侦听 socket),但是可能会导致多次触发;使用 ET 模式,我们必须每次都要将数据收完(对于普通 socket)或必须理解调用 accept 接收连接(对于侦听socket),其优点是触发次数少。
void *thread_roverdata(void* arg) { int i, ret; // Allocate memory for read buffer, set size according to your needs unsigned char read_buf [DATA_LEN]; // Normally you wouldn't do this memset() call, but since we will just receive // ASCII data for this example, we'll set everything to 0 so we can // call printf() easily. memset(&read_buf, '\0', sizeof(read_buf)); // Read bytes. The behaviour of read() (e.g. does it block?, // how long does it block for?) depends on the configuration // settings above, specifically VMIN and VTIME int num_bytes = 0; int len = 0; int epfd, nfds; struct epoll_event event; struct epoll_event* events; events=calloc(10, sizeof(event)); epfd = epoll_create(10); // 创建epoll实例 event.data.fd = uart5; // 添加标准输入到epoll event.events = EPOLLIN; // EPOLLET: epoll中的边沿触发的意思是只对新到的数据进行通知,而内核缓冲区中如果是旧数据则不进行通知 epoll_ctl(epfd, EPOLL_CTL_ADD, uart5, &event); for(;;) { ret = epoll_wait(epfd, events, 10, -1);// -1 :wait until it happen for(i=0; i<ret; i++) { if (events[i].data.fd == uart5) { num_bytes = read(events[i].data.fd, read_buf, DATA_LEN); if (num_bytes < 0) { UARTSendData((char*)"Error reading: %s\r\n", strerror(errno)); //while(1); } RTK_LOCATION_HandleRoverData(read_buf, num_bytes); // WriteFIFO(&save_fifo,read_buf, num_bytes); num_bytes = 0; } } } close(uart5); }
标签:epoll,read,模式,LT,串口,ET,event From: https://www.cnblogs.com/boring-luobo/p/18460329