真愛粉!國外粉絲將自己命名權小行星命名為吉田直樹
一、IO的過程
一次IO請求存在2個階段
階段一:等待資料,即資料從I/O裝置到核心記憶體(作業系統緩衝區)。(I/O裝置可能為磁碟, 也可能為網絡卡)
階段二:複製資料,即資料核心記憶體到程序記憶體(應用程式緩衝區)
阻塞/非阻塞,同步/非同步
階段一:阻塞/非阻塞 【DMA Copy】
階段二:同步/非同步 【CPU Copy】
二、I/O模型
(面試題)談談I/O模型?
1、首先I/O請求過程,指的是資料從IO裝置拷貝到使用者空間的步驟(兩步,等待資料和複製資料階段)
2、每種IO模型對這兩步的處理不同,像阻塞I/O模型,它對於這兩個階段都是阻塞的 ,非阻塞I/O模型,對於等待資料階段會對一個檔案描述符不斷髮起檢測,並會立即返回一個結果,如果可以,就阻塞進行復制資料階段,I/O複用模型在等待資料階段會阻塞,來檢查多個檔案描述符,不會立即返回結果,只要有一個檔案描述符可以工作,就阻塞進行復制資料階段,訊號驅動I/O模型在等待資料階段會發送一個訊號,並等待通知,然後阻塞完成複製資料階段,非同步I/O模型這兩個階段都是非阻塞的。
三、I/O多路複用
I/O多路複用執行程序同時檢查多個檔案描述符來找出他們中的任何一個是否可執行I/O操作
三種實現方式:
Select
Poll
Epoll
Select:通過設定或檢查存放fd標誌位的資料結構來進行下一步處理
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
缺點:
1、重複的CPU拷貝:每次呼叫select,都需要把fd集合從使用者態拷貝到核心態,這個開銷在fd很多時會很大
2、存在無效的遍歷:同時每次呼叫select都需要在核心遍歷傳遞進來的所有fd,這個開銷在fd很多時會很大
3、單執行緒select支援的檔案描述符受限於FD_SETSIZE巨集(即c的常量定義),是作業系統定義的,Linux預設是1024
Poll:本質與Select無區別,只是不受FD_SETSIZE巨集限制。
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
優點:採用連結串列的方式儲存pollfd,不受FD_SETSIZE限制,只受限於作業系統允許開啟的最大檔案描述符數目
缺點:
1、每次呼叫poll,都需要把pollfd連結串列從使用者態拷貝到核心態,這個開銷在fd很多時會很大
2、同時每次呼叫poll都需要在核心遍歷傳遞進來的所有fd,這個開銷在fd很多時會很大
Epoll:Event Poll,使用一個檔案描述符管理多個描述符,將使用者關心的檔案描述符事件放入核心到一個事件表中。
int epoll_create(int size):建立epoll檔案描述符
size:需要監聽的數目一共有多大。
返回值:一個檔案描述符(epfd),用於epoll_ctl、epoll_wait
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event):管理epoll監聽的檔案描述符與事件型別
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout):收集在epoll監控的事件中已發生的事件
優點:
1、epoll會在epoll_ctl()中註冊,只需要將所有的fd拷貝到核心事件表一次,不用再每次呼叫epoll_wait()時重複拷貝
2、epoll只返回就緒的描述符,減少無效的遍歷
3、能支援的fd數量是單個程序最大開啟檔案數
缺點:程式設計複雜
(面試題)什麼是I/O多路複用?
1、I/O多路複用是I/O請求的一種模型
2、它有三種實現方式,分別是select、poll以及epoll,對於select,它是通過設定和檢查存放fd標誌位的資料結果來進行下一步處理,它的缺點是重複的CPU拷貝,存在無效的遍歷、單執行緒select支援的檔案描述符還受限制(巨集限制,作業系統定義的),poll利用連結串列來儲存fd集合,使得單執行緒支援的檔案描述符不再受限於巨集,但是它的缺點仍然包括重複的CPU拷貝和存在無效的遍歷,而epoll是通過使用一個檔案描述符來管理多個檔案描述符,將使用者關心的檔案描述符事件放入核心事件表,所以不會重複的CPU拷貝,同時它只返回就緒的描述符,不會有無效的遍歷,支援的fd數量是單個程序能開啟的最大檔案數。
四、Java IO模型
三種IO模型:
1、OIO:Old IO,也可以叫BIO(Blocking-IO),同步阻塞IO
2、NIO:New IO,也可以叫NIO(None-Blocking IO),同步非阻塞IO 【JDK 1.4+】
3、AIO:非同步非阻塞IO 【JDK1.7+】
‘
BIO對應 Linux IO模型的阻塞IO
’NIO和AIO對應Linux IO模型的IO多路複用,並且都是使用epoll實現
OIO
1、抽象模型可以分為:流、輸入輸出流、字元位元組流,就是InputStream、OutStream、Reader、Writer
2、ServerSocket和Socket程式呼叫會阻塞,所以也將此類歸結於BIO中。
NIO
1、抽象模型可以分為:Channel管理、Buffer緩衝、Selector選擇器
Channel與Buffer:資料總是從通道讀取到緩衝區中,或者從緩衝區寫入到通道中。
Selector:允許單執行緒處理多個 Channel
OIO和NIO的區別
NIO的Buffer:一塊可以寫入資料,也可以從中讀取資料的記憶體物件。
運用到了介面卡模式、裝飾器模式
基本屬性:
容量(capacity):緩衝區能夠容納元素的最大數量
上界(limit):緩衝區實際容納元素的數量
位置(position):下一個要被讀寫的元素的陣列下標索引
buffer.flip():Buffer讀寫模型的切換 limit設定為position當前的值;postion會被置為0。
Selector:選擇器,多路複用器,能夠檢測一到多個NIO通道,並能夠知曉通道是否為諸如讀寫事件做好準備的元件。
過程:
1、建立Selector
Selector selector = Selector.open();
2、向Slector註冊通道【FileChannel不可以註冊】
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, Selectionkey.感興趣的事件);
3、開始工作,阻塞到至少有一個通道在你註冊的事件上就緒
selector.select()
4、獲取就緒的事件集合 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 5、消費就緒的事件
EPOLL_CTL_ADD:註冊新的fd到epfd中EPOLL_CTL_MOD:修改已經註冊的fd的監聽事件EPOLL_CTL_DEL:從epfd中刪除一個fd