Unix下可用的5中I/O模型
一個(gè)輸入操作通常包含兩個(gè)不同階段
等待數(shù)據(jù)準(zhǔn)備好。
從內(nèi)核向進(jìn)程復(fù)制數(shù)據(jù)。
第一步通常涉及等待數(shù)據(jù)從網(wǎng)絡(luò)中到達(dá),當(dāng)所等待分組到達(dá)時(shí),他被復(fù)制到內(nèi)核中的某個(gè)緩沖區(qū)。
第二步是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)。
1. 阻塞式I/O

進(jìn)程調(diào)用recvfrom,其系統(tǒng)調(diào)用知道數(shù)據(jù)到達(dá)且被復(fù)制到應(yīng)用進(jìn)程的緩沖區(qū)中,或者發(fā)生錯(cuò)誤才返回。從調(diào)用recvfrom開(kāi)始,到它返回的整段時(shí)間內(nèi)是被阻塞的。recvfrom成功返回后,應(yīng)用進(jìn)程開(kāi)始處理數(shù)據(jù)。
非阻塞式I/O

進(jìn)程把一個(gè)套接字設(shè)置成非阻塞是在通知內(nèi)核:當(dāng)所請(qǐng)求的IO操作時(shí),不進(jìn)行阻塞,而是返回一個(gè)錯(cuò)誤。當(dāng)應(yīng)用進(jìn)程像對(duì)這樣一個(gè)非阻塞描述符循環(huán)調(diào)用recvfrom時(shí),稱之為輪詢。
應(yīng)用進(jìn)程持持續(xù)輪詢內(nèi)核,以便查看某個(gè)操作是否就緒、這樣做往往消耗大量CPU時(shí)間。
I/O復(fù)用(select 和 poll)

阻塞與select調(diào)用,等待數(shù)據(jù)報(bào)套接字變?yōu)榭勺x,。當(dāng)select返回套接字可讀這一條件,調(diào)用recvfrom把可讀數(shù)據(jù)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)。
使用IO復(fù)用并沒(méi)有什么優(yōu)勢(shì),而且還需要兩個(gè)系統(tǒng)調(diào)用。但是select的優(yōu)勢(shì),在于可以等待多個(gè)描述符就緒。
信號(hào)驅(qū)動(dòng)式I/O(SIGIO)

首先要開(kāi)啟套接字的信號(hào)驅(qū)動(dòng)式IO功能,并通過(guò)系統(tǒng)調(diào)用,安裝一個(gè)信號(hào)處理函數(shù),該調(diào)用會(huì)立即返回,進(jìn)程可以繼續(xù)工作,不會(huì)阻塞。
當(dāng)數(shù)據(jù)準(zhǔn)備好,內(nèi)核就為該進(jìn)程產(chǎn)生一個(gè)SIGIO信號(hào)。隨后可以在信號(hào)處理函數(shù)中調(diào)用revcfrom讀取數(shù)據(jù),并通知主循環(huán)數(shù)據(jù)已經(jīng)準(zhǔn)備好處理。
這種模型優(yōu)勢(shì)在于,等待數(shù)據(jù)到達(dá)期間,進(jìn)程不會(huì)被阻塞,主循環(huán)可以繼續(xù)執(zhí)行。
異步I/O

工作機(jī)制是:告知內(nèi)核后啟動(dòng)某個(gè)操作,并讓內(nèi)核在整個(gè)操作(包括將數(shù)據(jù)從內(nèi)核復(fù)制到進(jìn)程緩沖區(qū)),完成后通知進(jìn)程。信號(hào)驅(qū)動(dòng)的話,只是由內(nèi)核通知進(jìn)程可以啟動(dòng)一個(gè)IO操作。異步IO是內(nèi)核通知應(yīng)用進(jìn)程IO操作何時(shí)完成。
同步IO操作:導(dǎo)致請(qǐng)求進(jìn)程阻塞,直到IO操作完成。
異步IO操作:不導(dǎo)致請(qǐng)求進(jìn)程阻塞。
因此可以知道:阻塞IO模型、非阻塞IO模型、IO復(fù)用模型和信號(hào)驅(qū)動(dòng)IO模型 都是同步IO模型,因?yàn)檎嬲腎O操作(recvfrom)將阻塞進(jìn)程。只有異步IO模型 是異步IO。
參考資料
- 《UNIX網(wǎng)絡(luò)編程卷1》第6章 6.2 I/O模型