操作系统学习:IO多路复用
最基本的socket模型
我记得socket其实就是对应用层以下的部分进行打包,也就是传输层,网络层,网络发送层
每次使用的时候就创建一个socket,为其指定IP和端口,让这个socket可以被找到,然后启动listen监听
服务端监听后,调用accept()会去连接池拿已经握手成功的tcp连接
注意这里有两个socket,一个监听,一个接收发送数据
本质上socket也是一个文件,通过文件读写来实现接收发送数据,毕竟linux一切皆文件
多进程模型
每个客户端fork一个子进程来处理网络请求
这里其实还是一个socket,因为子进程fork父进程的时候同时会获取socket
坏处:
- 子进程不好好处理会变成僵尸进程,消耗系统资源
- 进程上下文开销太大,切换上下文需要保存栈,文件描述符,寄存器等东西
多线程模型
多进程开销太大,就换成线程来
维护一个线程池子,每次新连接建立,就把建立的socket放到队列里,然后从线程池里取一个来处理
缺点:需要多线程处理加锁
IO多路复用
多线程,多进程本质都是一个进程/线程处理一个socket
IO多路复用就是一个进程处理多个socket
select/poll
处理方法就是,操作系统把已经建立连接的socket的文件描述符,放到一个集合里,然后拷贝给内核态
内核态接收到网络请求,就标记这个socket,然后把整个集合传回用户态,用户态再遍历找到这个socket处理
都是线性结构,两次拷贝两次遍历都很消耗时间
epoll
epoll优化的地方是数据结构,不再使用集合,而是在内存里使用红黑树来维护建立连接的socket,使用链表来维护有请求的socket
边缘触发vs水平触发
边缘触发,就是第一次满足条件就通知,之后不再通知,所以也尽可能一次就读取完所有数据
水平触发,就是只要满足条件就不断通知
select/poll是水平触发
epoll是边缘触发,更高效
操作系统学习:IO多路复用
http://example.com/2024/07/01/操作系统学习:IO多路复用/