auto commit
This commit is contained in:
@ -1,23 +1,13 @@
|
||||
# Socket
|
||||
<!-- GFM-TOC -->
|
||||
* [一、I/O 模型](#一io-模型)
|
||||
* [阻塞式 I/O](#阻塞式-io)
|
||||
* [非阻塞式 I/O](#非阻塞式-io)
|
||||
* [I/O 复用](#io-复用)
|
||||
* [信号驱动 I/O](#信号驱动-io)
|
||||
* [异步 I/O](#异步-io)
|
||||
* [五大 I/O 模型比较](#五大-io-模型比较)
|
||||
* [二、I/O 复用](#二io-复用)
|
||||
* [select](#select)
|
||||
* [poll](#poll)
|
||||
* [比较](#比较)
|
||||
* [epoll](#epoll)
|
||||
* [工作模式](#工作模式)
|
||||
* [应用场景](#应用场景)
|
||||
* [参考资料](#参考资料)
|
||||
* [Socket](#socket)
|
||||
* [一、I/O 模型](#一io-模型)
|
||||
* [二、I/O 复用](#二io-复用)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
# 一、I/O 模型
|
||||
## 一、I/O 模型
|
||||
|
||||
一个输入操作通常包括两个阶段:
|
||||
|
||||
@ -34,7 +24,7 @@ Unix 有五种 I/O 模型:
|
||||
- 信号驱动式 I/O(SIGIO)
|
||||
- 异步 I/O(AIO)
|
||||
|
||||
## 阻塞式 I/O
|
||||
### 阻塞式 I/O
|
||||
|
||||
应用进程被阻塞,直到数据从内核缓冲区复制到应用进程缓冲区中才返回。
|
||||
|
||||
@ -48,7 +38,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492928416812_4.png"/> </div><br>
|
||||
|
||||
## 非阻塞式 I/O
|
||||
### 非阻塞式 I/O
|
||||
|
||||
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。
|
||||
|
||||
@ -56,7 +46,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492929000361_5.png"/> </div><br>
|
||||
|
||||
## I/O 复用
|
||||
### I/O 复用
|
||||
|
||||
使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。
|
||||
|
||||
@ -66,7 +56,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492929444818_6.png"/> </div><br>
|
||||
|
||||
## 信号驱动 I/O
|
||||
### 信号驱动 I/O
|
||||
|
||||
应用进程使用 sigaction 系统调用,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recvfrom 将数据从内核复制到应用进程中。
|
||||
|
||||
@ -74,7 +64,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492929553651_7.png"/> </div><br>
|
||||
|
||||
## 异步 I/O
|
||||
### 异步 I/O
|
||||
|
||||
应用进程执行 aio_read 系统调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
|
||||
|
||||
@ -82,7 +72,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492930243286_8.png"/> </div><br>
|
||||
|
||||
## 五大 I/O 模型比较
|
||||
### 五大 I/O 模型比较
|
||||
|
||||
- 同步 I/O:将数据从内核缓冲区复制到应用进程缓冲区的阶段(第二阶段),应用进程会阻塞。
|
||||
- 异步 I/O:第二阶段应用进程不会阻塞。
|
||||
@ -93,11 +83,11 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/1492928105791_3.png"/> </div><br>
|
||||
|
||||
# 二、I/O 复用
|
||||
## 二、I/O 复用
|
||||
|
||||
select/poll/epoll 都是 I/O 多路复用的具体实现,select 出现的最早,之后是 poll,再是 epoll。
|
||||
|
||||
## select
|
||||
### select
|
||||
|
||||
```c
|
||||
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
@ -150,7 +140,7 @@ else
|
||||
}
|
||||
```
|
||||
|
||||
## poll
|
||||
### poll
|
||||
|
||||
```c
|
||||
int poll(struct pollfd *fds, unsigned int nfds, int timeout);
|
||||
@ -201,9 +191,9 @@ else
|
||||
}
|
||||
```
|
||||
|
||||
## 比较
|
||||
### 比较
|
||||
|
||||
### 1. 功能
|
||||
#### 1. 功能
|
||||
|
||||
select 和 poll 的功能基本相同,不过在一些实现细节上有所不同。
|
||||
|
||||
@ -212,15 +202,15 @@ select 和 poll 的功能基本相同,不过在一些实现细节上有所不
|
||||
- poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高。
|
||||
- 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定。
|
||||
|
||||
### 2. 速度
|
||||
#### 2. 速度
|
||||
|
||||
select 和 poll 速度都比较慢,每次调用都需要将全部描述符从应用进程缓冲区复制到内核缓冲区。
|
||||
|
||||
### 3. 可移植性
|
||||
#### 3. 可移植性
|
||||
|
||||
几乎所有的系统都支持 select,但是只有比较新的系统支持 poll。
|
||||
|
||||
## epoll
|
||||
### epoll
|
||||
|
||||
```c
|
||||
int epoll_create(int size);
|
||||
@ -286,35 +276,35 @@ else
|
||||
```
|
||||
|
||||
|
||||
## 工作模式
|
||||
### 工作模式
|
||||
|
||||
epoll 的描述符事件有两种触发模式:LT(level trigger)和 ET(edge trigger)。
|
||||
|
||||
### 1. LT 模式
|
||||
#### 1. LT 模式
|
||||
|
||||
当 epoll_wait() 检测到描述符事件到达时,将此事件通知进程,进程可以不立即处理该事件,下次调用 epoll_wait() 会再次通知进程。是默认的一种模式,并且同时支持 Blocking 和 No-Blocking。
|
||||
|
||||
### 2. ET 模式
|
||||
#### 2. ET 模式
|
||||
|
||||
和 LT 模式不同的是,通知之后进程必须立即处理事件,下次再调用 epoll_wait() 时不会再得到事件到达的通知。
|
||||
|
||||
很大程度上减少了 epoll 事件被重复触发的次数,因此效率要比 LT 模式高。只支持 No-Blocking,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
|
||||
|
||||
## 应用场景
|
||||
### 应用场景
|
||||
|
||||
很容易产生一种错觉认为只要用 epoll 就可以了,select 和 poll 都已经过时了,其实它们都有各自的使用场景。
|
||||
|
||||
### 1. select 应用场景
|
||||
#### 1. select 应用场景
|
||||
|
||||
select 的 timeout 参数精度为微秒,而 poll 和 epoll 为毫秒,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。
|
||||
|
||||
select 可移植性更好,几乎被所有主流平台所支持。
|
||||
|
||||
### 2. poll 应用场景
|
||||
#### 2. poll 应用场景
|
||||
|
||||
poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。
|
||||
|
||||
### 3. epoll 应用场景
|
||||
#### 3. epoll 应用场景
|
||||
|
||||
只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。
|
||||
|
||||
@ -322,7 +312,7 @@ poll 没有最大描述符数量的限制,如果平台支持并且对实时性
|
||||
|
||||
需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。
|
||||
|
||||
# 参考资料
|
||||
## 参考资料
|
||||
|
||||
- Stevens W R, Fenner B, Rudoff A M. UNIX network programming[M]. Addison-Wesley Professional, 2004.
|
||||
- http://man7.org/linux/man-pages/man2/select.2.html
|
||||
@ -333,10 +323,3 @@ poll 没有最大描述符数量的限制,如果平台支持并且对实时性
|
||||
- [poll vs select vs event-based](https://daniel.haxx.se/docs/poll-vs-select.html)
|
||||
- [select / poll / epoll: practical difference for system architects](http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/)
|
||||
- [Browse the source code of userspace/glibc/sysdeps/unix/sysv/linux/ online](https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>
|
||||
|
Reference in New Issue
Block a user