int iResult = recv(s, buffer,1024);
/*设置非阻塞模式,立即返回*/
int iResult = ioctlsocket(s, FIOBIO, (unsigned long *)&ul);
iResult = recv(s, buffer,1024);
//5种io模型,两个步骤,1等待数据到内核,2从内核拿数据
bio : 一直等待数据到内核,然后copy
recvfrom -> [syscall -> wait -> copy ->] return OK
nbio: 内核无数据返回,有数据然后copy
recvfrom -> [syscall -> wait ->] return no data ready
recvfrom -> [syscall -> wait ->] return no data ready
recvfrom -> [syscall -> wait ->] return ready
recvfrom -> [syscall -> copy ->] return OK
io multiplexing
每个IO都是非阻塞IO,第一阶段通过select/poll方法,一次性轮询多个IO句柄,检查是否有IO句柄准备好,第二阶段阻塞读取数据
select/pool -> [syscall -> wait ->] return readable
recvfrom -> [syscall -> copy ->] return OK
NIO和IO多路复用是两个相对独立的事情,IO多路复用和NIO是要配合一起使用才有实际
//select
支持了同一个线程内同时处理多个IO请求
每次所有fd到内核,内核每次遍历所有fd,数量有限
可以cat/proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048
sizeof(fd_set)=512,每bit表示一个文件描述符,支持的最大文件描述符是512*8=4096
//poll
poll没有最大文件描述符数量的限制
使用pollfd结构而不是select的fd_set结构
//epoll
epoll_create是创建一个epoll句柄;epoll_ctl是注册要监听的事件类型;epoll_wait则是等待事件的产生
epoll保证了每个fd在整个过程中只会拷贝一次
虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,
而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间
水平触发和边沿触发,有数据触发,有新数据触发
signal driven IO
构造一个信号处理器回调,第二阶段阻塞读取数据
signal handle -> [syscall -> wait ->] return
[syscall ->] signal handle -> recvfrom -> [syscall -> copy ->] return OK
asynchronous IO
两阶段都是非阻塞
aio_read -> [syscall -> wait ->] return
[syscall -> copy ->] aio_read callback
linux的AIO的实现方式是内核和应用共享一片内存区域,来得知fd是否有数据
网络IO select epoll
最新推荐文章于 2024-06-14 20:45:42 发布