0%
IO model
introduction
Kernal Space, User Space
- 作業系統的核心是核心,獨立於普通的應用程式,可以訪問受保護的記憶體空間,也有訪問底層硬體裝置的所有許可權。為了保證使用者程式不能直接操作核心(kernel),保證核心的安全
- CPU 執行程式時,會在 user space 與 kernel space 之間來回切換,user space 的系統函式庫,會轉換為 kernel space 的 system call,並由 kernel 處理,當 system call 完成後,就會回到 user space 繼續下去。
- 32 bits 的 OS,定址空間是 2^32 也就是 4G。kernel space 限制為 1G (虛擬地址0xC0000000到0xFFFFFFFF),而 user space 為 3G (虛擬地址0x00000000到0xBFFFFFFF),由各 process 使用。
- 64 bits 的 OS,會將 virtual address 分成一半,第一個 bit 為 0 是 user space,第一個 bit 為 1 是 kernel space,理論上是 8EB+8EB。但目前 processors 只實作了 48 bits,也就是 128TB+128TB。
Buffered I/O
- 大多數文件系統的默認I/O 操作都是 Buffered I/O,在 Linux 會將 IO 資料先暫存在 page cache 中,也就是先複製到 kernel 的 buffer,然後再由 kernel buffer 複製到 user space。
- Buffered I/O 分離了 user space 及實際的儲存設備,可以減少 HD 的讀取次數,提高系統效能。
- 但也因為多次複製,可能會造成 CPU 及 cache buffer 的消耗,有些特殊的應用,會避開 kernel cache buffer,而直接由 user space 儲存到 HD,以獲取更高的效能。
IO model
- 因為資料會先複製到 kernel buffer 裡面,然後再複製到 user space,當對一個資料進行 read,會經歷兩個階段:
- waiting for data to be ready
- copying the data from the kernel to the process
- 因為兩階段的 IO,linux 產生了五種 IO model
- blocking IO
- nonblocking IO
- IO multiplexing
- signal driven IO (不常用)
- asynchronous IO
blocking IO
- linux 預設大部分的 socket 都是使用 blocking IO
- 當 process 呼叫 recv_from,會進入 wait for data 階段,在這個階段的 process 會進入 blocking 狀態,直到 kernel 將資料複製到 user space,該 process 才會解除 blocking 狀態,重新運作。
- blocking IO 就是兩個階段的 IO 都被 block
nonblocking IO
- 當 process 呼叫 recv_from 如果 kernel 還沒將資料準備好,他不會 block process,而是產生 error,直到 kernel 將資料準備好,就會複製到 user space,並完成該讀取的工作。
- nonblocking 需要 process 不斷向 kernel 詢問,資料是否 ready。
IO multiplexing
- 這就是常見的 select, poll, epoll,也稱為 event driven IO。
- 這個方式可讓單一 porcess 就可以處理多個 IO,他會不斷地 polling 多個 socket,當某個 socket 有收到資料,就會主動callback 通知 process。
- 如果是 select,當 process 呼叫了 select,該 process 就會被 block,同時 kernel 會監控所有 select 處理的 sockets,如果有資料,select 就會 return,然後再由 process 呼叫 read,將資料由 kernel 複製到 user space。
- 這個方法類似 blocking IO,但進行了兩個 system call (select 及 recv_from),但 select 可處理多個 sockets。
- select/epoll 的優點是可以處理多個 sockets,而不是效能。一般在 IO multiplexing 中,socket 都是設定為 non-blocking 的,process 是在 select 被 block 而不是 recv_from。
signal driven
- 先通知 kernel 如果某個 socket 有資料時,就以 signal 通知 process,process 在第二個步驟,才會被 block。
asynchronous
- 當 process 進行 read,就可以處理別的事情,當 kernel 收到非同步 read,就會馬上 return,直到將資料複製到 user space,完成後,才會發送 signal 給 process,通知已經完成了 read。
Comparison
- non-blocking 跟 asynchronous 是不同的
- synchronous 跟 asynchronous 的差異是 IO operation 會不會 blocking process,因此前面四種 model 都屬於 synchronous IO
- nonblocking IO 中,在複製資料到 user space 的步驟,還是會有 blocking 的狀態
reference