一.分类
1.同步阻塞
2.同步非阻塞
3.IO多路复用(+多线程的组合比较常用):异步阻塞
4.异步IO
二.不常用的两种方式
1.用户线程和内核IO交互方式
同步:用户线程等待内核IO完成才能继续进行
异步:用户线程发起IO请求以后继续进行,内核会毁掉或者通知用户线程
2.阻塞:等待,浪费cpu
非阻塞:一直轮询查询,耗费cpu
3.同步阻塞:
{
read(socket,buffer);
process(buffer);
}
同步非阻塞
while(read(socket,buffer) != SUCCESS)
{
process(buffer);
}
三.应用广泛的IO多路复用模式
1.采用reactor(异步阻塞)+select多路分离函数(同步阻塞)
2.select能支持多个socket监听,而同步需要多线程才能实现,但是每一个socket也是非阻塞监听的,但是select函数会阻塞线程
select(socket1);
while(1)
{
sockets = select();
for(socket1 in sockets)
if(can_read(socket1))
read(socket1,buffer);
process(buffer);
for(socket2)
............;
}
3.reactor用户向select添加socket,并且使用reactor处理返回的请求,select函数执行时线程被阻塞
图解:通过Reactor的方式,可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。用户线程注册事件处理器之后可以继续执行做其他的工作(异步),而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时,则通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。
void UserEventHandler::handle_event()
{
if(can_read(socket))
read(socket,buffer);
process(buffer);
}
Reactor::handle_events()
{
while(1)
sockets = select();
for(socket int sockets)
ge_event_handler(socket).handle_event();
}