- I/O多路服用
- 信號驅動I/O
- Linux特有的epoll編程接口
O_NONBLOCK非阻塞IO
### 什么是文件描述符?
文件描述符是用于指代被打開的文件
### IO多路復用
可以同時檢測多個文件描述符,select(), poll();這兩個系統調用要么等待文件描述符成為就緒態,要么在調用中設定一個超時時間;
#### select
```c
// returns number of read file descriptors, 0 on timeout, -1 on error
#include <sys/time.h>
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
```
- nfds 需要檢測的文件描述符最大符號,通過設置該值,select()變得更加效率,因為不需要檢測大于nfds的其他文件描述符號
- readfds 檢測輸入是否就緒的文件描述符集合(保存結果的地方)
- writefds 檢測輸出是否就緒的文件描述符集合(保存結果的地方)
- exceptfds 檢測異常情況的文件描述符集合(保存結果的地方)
- timeout 為NULL時,select將一直阻塞,timeout結構如下:
```c
struct timeval {
time_t tv_sec;
suseconds_t tv_usec; // 微妙
}
```
文件描述符集合由宏來操作
```c
#include <sys/select.h>
void FD_ZERO(fd_set *fdset)
void FD_SET(int fd, fd_set *fdset)
void FD_CLR(int fd, fd_set *fdset)
void FD_ISSET(int fd, fd_set *fdset)
```
- FD_ZERO() 將fdset指向的文件描述符集合初始化為空
- FD_SET() 將fd添加到fdset文件描述符集合
- FD_CLR() 將fd從fdset文件描述符集合移除
- FD_ISSET() fd是否為fdset文件描述符集合成員
文件描述符集合容量限制有FD_SETSIZE決定
#### poll
```c
// returns number of read file descriptors, 0 on timeout,or -1 on error
#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
```
struct pollfd結構如下:
```c
struct pollfd {
int fd;
short events;
short revents;
}
```
### select和poll就緒態
select和poll只會告訴我們IO操作是否阻塞,而不是告訴我們能否成功傳輸數據
不同類型的描述符
### 信號驅動
進程可以處理其他任務,當有數據寫入到文件描述符時,內核向調用數據的進程發送信號;在檢測大量文件描述符時,信號驅動比select()和poll()有優勢
### epoll
epoll優點如下:
- epoll是Linux特有的,可以同時檢測多個文件描述符,并且性能比select()和poll()好;
- 支持兩種模式,水平觸發(level trigger),邊緣觸發(edge trigger),默認是LT模式
#### epoll api
```c
int epoll_create(int size)
```
創建一個epoll句柄,size表示告訴內核要監控多少個fd;創建之后會占用一個fd,在使用晚時需要close掉
```c
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
```
事件注冊函數
- epfd 由epoll_create創建返回的句柄
- op
- EPOLL_CTL_ADD 添加一個fd到epfd
- EPOLL_CTL_MOD 修改已注冊的fd的監聽事件
- EPOLL_CTL_DEL 從epfd刪除一個fd
- fd 需要監聽的fd
- struct epoll_event *event 監聽事件,結構如下:
```c
struct epoll_event {
__unit32_t events; // 例如EPOLLIN,EPOLLOUT
epoll_data_t data;
}
```
```C
// 返回需要處理的事件數目
int epoll_wait(int epfd, struct epoll_event *event, int maxevents, int timeout)
```
等待事件的發生
### libEvent
libEvent提供了檢查文件描述符IO事件的抽象;Libevent底層機制能夠以透明的方式應用select(),poll(),epoll(),信號驅動等任意一種技術
### 工作模式(水平觸發,邊緣觸發)
- 水平觸發:檢測到文件描述符有事件發送并通知應用程序,應用程序可以不立即處理事件
- 邊緣觸發:檢測到文件描述符有事件發送并通知應用程序,應用程序必須立即處理事件
各種IO模式通知模式如下:
|IO模式|水平觸發|邊緣觸發|
|:---:|:---:|:---:|
|select(),poll()|Y|N|
|信號驅動|N|Y|
|epoll|Y|Y|
- php
- 編譯安裝
- 基本概念
- 垃圾回收機制
- 生命周期
- zval底層實現
- c擴展開發
- gdb調試工具
- 自定義擴展簡單demo
- 鉤子函數
- 讀取php.ini配置
- 數組
- 函數
- 類
- yaf擴展底層源碼
- swoole擴展底層源碼
- memoryGlobal內存池
- swoole協程使用記錄
- 單點登錄sso原理
- compser使用
- session實現機制
- c & linux
- gcc
- 指針
- 結構體,聯合和位字段
- 宏定義井號說明
- printf家族函數和可變參數
- 共享函數
- 靜態庫和動態庫
- makefile自動化構建
- 信號一
- 信號二
- inotify監控文件事件
- socket編程
- 簡介
- UNIX DOMAIN
- Internet DOMAIN
- TCP/IP
- 文件IO多路復用
- 內存管理
- 進程組,會話和控制終端
- daemon守護進程
- 多進程
- 多線程
- 常用進制轉換
- go
- 入門知識
- 字節和整數裝換
- python
- redis
- 應用場景
- 消息隊列
- 熱點數據
- 掃碼登錄
- 訂閱發布
- 次數限制
- 搶購超賣
- 持久化機制
- mysql
- 工作流程
- MyISAM和InnoDB區別
- 用戶和權限管理
- 執行計劃
- sql優化
- 事務和鎖
- 慢查詢日志
- case...when...then...end用法
- sql
- 參考
- linux
- 內核參數優化
- 防火墻設置
- docker
- docker入門知識
- 算法
- 多維數組合
- DFA算法
- 紅包金額分配