在学习网络IO的时候总是被阻塞/非阻塞, 同步/异步搞得团团转, 本文是自己对这部分的一些学习心得
IO模型
小明去打水
杯子:用户空间
水:数据
饮水机:内核空间
阻塞/非阻塞IO
小明拿杯子去打水, 饮水机内不一定有水, 当饮水机没水
- 他就在原地等待, 直到饮水机有水, 阻塞IO
- 他就先离开, 等一会儿再来看看饮水机有没有水, 非阻塞IO
- recv时可设置成阻塞和非阻塞
- 阻塞时, 会一直等待, 直到有数据了才往下执行
- 非阻塞时, 当没有数据时, 便会直接返回, 往下执行
IO复用
小明厌倦了总是要亲自去看饮水机有没有水, 因此他让宿管阿姨帮忙, 如果有水再叫他过来打
这次宿舍楼有多台饮水机
- 宿管阿姨只告诉小明饮水机有水, 但没告诉他是哪台饮水机有水, 小明只能挨个去试, select
- 宿管阿姨不仅告诉小明饮水机有水, 还告诉他哪几台有水, 因此小明只有去有水的饮水机那里打水就可以了, epoll
- 在recv前, 先调用select/epoll, 如果有数据, 那么才recv
- 因为recv时肯定是有数据的, 所以可以当是非阻塞
- select/epoll可设置超时时间
同步/异步IO
小明拿杯子去打水, 假设现在饮水机有水了
- 打水时, 等待杯子盛满(内核层->应用层), 同步IO
- 不等杯子盛满, 先离开, 等杯子满后, 宿管阿姨通知他, 异步IO
- 同步IO是等待内核空间将数据拷贝到用户空间 (recv等是同步IO)
- 异步IO是不等待拷贝, 可以先去执行其他任务, 等到数据拷贝完成时再通知 (aio_read是异步IO)