为什么ET模式需要将文件设置为非阻塞的原因

阻塞IO:当你去读一个阻塞的文件描述符时,如果在该文件描述符上没有数据可读,那么它会一直阻塞(通俗一点就是一直卡在调用函数那里),直到有数据可读。当你去写一个阻塞的文件描述符时,如果在该文件描述符上没有空间(通常是缓冲区)可写,那么它会一直阻塞,直到有空间可写。以上的读和写我们统一指在某个文件描述符进行的操作,不单单指真正的读数据,写数据,还包括接收连接accept(),发起连接connect()等操作…

非阻塞IO:当你去读写一个非阻塞的文件描述符时,不管可不可以读写,它都会立即返回,返回成功说明读写操作完成了,返回失败会设置相应errno状态码,根据这个errno可以进一步执行其他处理。它不会像阻塞IO那样,卡在那里不动!!!

Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!!!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!!!

Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!!!
所以ET所以循环处理,保证能将数据读取完毕,即同时要保证非阻塞IO,不然最后会被阻塞

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 设置socket非阻塞模式 在创建socket后,使用fcntl函数设置socket非阻塞模式。例如: ```c int sock = socket(AF_INET, SOCK_STREAM, 0); fcntl(sock, F_SETFL, O_NONBLOCK); ``` 2. 使用select函数进行异步通信 在非阻塞模式下,使用select函数可以实现异步通信。select函数可以同时监听多个socket文件描述符,当其中一个文件描述符上有数据可读或可写时,select函数会返回。例如: ```c fd_set read_fds, write_fds; FD_ZERO(&read_fds); FD_ZERO(&write_fds); FD_SET(sock, &read_fds); FD_SET(sock, &write_fds); struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; int ret = select(sock + 1, &read_fds, &write_fds, NULL, &timeout); if (ret < 0) { perror("select error"); } else if (ret == 0) { printf("select timeout\n"); } else { if (FD_ISSET(sock, &read_fds)) { // socket可读 } if (FD_ISSET(sock, &write_fds)) { // socket可写 } } ``` 3. 使用epoll函数进行异步通信 epoll是Linux中高效的异步I/O机制。使用epoll可以监听多个文件描述符,当其中一个文件描述符上有数据可读或可写时,epoll会通知应用程序。例如: ```c int epfd = epoll_create(10); struct epoll_event ev; ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.fd = sock; epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev); struct epoll_event events[10]; int ret = epoll_wait(epfd, events, 10, 5000); if (ret < 0) { perror("epoll_wait error"); } else if (ret == 0) { printf("epoll timeout\n"); } else { for (int i = 0; i < ret; ++i) { if (events[i].events & EPOLLIN) { // socket可读 } if (events[i].events & EPOLLOUT) { // socket可写 } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值