您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何淺析編程語言中的五種編程模型,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
編程模型,我們可以簡單地理解為,它就是模板,遇到相似問題就可以方便依模板解決,這樣就簡化了編程問題。不同的編程環(huán)境和不同的應用對象有不同的編程模型。編程模型也是學習編程內(nèi)容中的基礎知識,小編帶著大家來淺析五種編程模型。
一、同步異步,阻塞非阻塞區(qū)別聯(lián)系
實際上同步與異步是針對應用程序與內(nèi)核的交互而言的。同步過程中進程觸發(fā)IO操作并等待(也就是我們說的阻塞)或者輪詢的去查看IO操作(也就是我們說的非阻塞)是否完成。異步過程中進程觸發(fā)IO操作以后,直接返回,做自己的事情,IO交給內(nèi)核來處理,完成后內(nèi)核通知進程IO完成。同步和異步針對應用程序來,關注的是程序中間的協(xié)作關系;阻塞與非阻塞更關注的是單個進程的執(zhí)行狀態(tài)。同步有阻塞和非阻塞之分,異步?jīng)]有,它一定是非阻塞的。阻塞、非阻塞、多路IO復用,都是同步IO,異步必定是非阻塞的,所以不存在異步阻塞和異步非阻塞的說法。真正的異步IO需要CPU的深度參與。換句話說,只有用戶線程在操作IO的時候根本不去考慮IO的執(zhí)行全部都交給CPU去完成,而自己只等待一個完成信號的時候,才是真正的異步IO。所以,拉一個子線程去輪詢、去死循環(huán),或者使用select、poll、epool,都不是異步。
同步:執(zhí)行一個操作之后,進程觸發(fā)IO操作并等待(也就是我們說的阻塞)或者輪詢的去查看IO操作(也就是我們說的非阻塞)是否完成,等待結(jié)果,然后才繼續(xù)執(zhí)行后續(xù)的操作。
異步:執(zhí)行一個操作后,可以去執(zhí)行其他的操作,然后等待通知再回來執(zhí)行剛才沒執(zhí)行完的操作。
阻塞:進程給CPU傳達一個任務之后,一直等待CPU處理完成,然后才執(zhí)行后面的操作。
非阻塞:進程給CPU傳達任我后,繼續(xù)處理后續(xù)的操作,隔斷時間再來詢問之前的操作是否完成。這樣的過程其實也叫輪詢。
二、IO模型(五種編程模型)
這里統(tǒng)一使用Linux下的系統(tǒng)調(diào)用recv作為例子,它用于從套接字上接收一個消息,因為是一個系統(tǒng)調(diào)用,所以調(diào)用時會從用戶進程空間切換到內(nèi)核空間運行一段時間再切換回來。默認情況下recv會等到網(wǎng)絡數(shù)據(jù)到達并且復制到用戶進程空間或者發(fā)生錯誤時返回,而第4個參數(shù)flags可以讓它馬上返回。
1、阻塞IO模型
使用recv的默認參數(shù)一直等數(shù)據(jù)直到拷貝到用戶空間,這段時間內(nèi)進程始終阻塞。A同學用杯子裝水,打開水龍頭裝滿水然后離開。這一過程就可以看成是使用了阻塞IO模型,因為如果水龍頭沒有水,他也要等到有水并裝滿杯子才能離開去做別的事情。很顯然,這種IO模型是同步的。
2、非阻塞IO模型
改變flags,讓recv不管有沒有獲取到數(shù)據(jù)都返回,如果沒有數(shù)據(jù)那么一段時間后再調(diào)用recv看看,如此循環(huán)。B同學也用杯子裝水,打開水龍頭后發(fā)現(xiàn)沒有水,它離開了,過一會他又拿著杯子來看看……在中間離開的這些時間里,B同學離開了裝水現(xiàn)場(回到用戶進程空間),可以做他自己的事情。這就是非阻塞IO模型。但是它只有是檢查無數(shù)據(jù)的時候是非阻塞的,在數(shù)據(jù)到達的時候依然要等待復制數(shù)據(jù)到用戶空間(等著水將水杯裝滿),因此它還是同步IO。
3、IO復用模型
這里在調(diào)用recv前先調(diào)用select或者poll,這2個系統(tǒng)調(diào)用都可以在內(nèi)核準備好數(shù)據(jù)(網(wǎng)絡數(shù)據(jù)到達內(nèi)核)時告知用戶進程,這個時候再調(diào)用recv一定是有數(shù)據(jù)的。因此這一過程中它是阻塞于select或poll,而沒有阻塞于recv,有人將非阻塞IO定義成在讀寫操作時沒有阻塞于系統(tǒng)調(diào)用的IO操作(不包括數(shù)據(jù)從內(nèi)核復制到用戶空間時的阻塞,因為這相對于網(wǎng)絡IO來說確實很短暫),如果按這樣理解,這種IO模型也能稱之為非阻塞IO模型,但是按POSIX來看,它也是同步IO,那么也和樓上一樣稱之為同步非阻塞IO吧。
這種IO模型比較特別,分個段。因為它能同時監(jiān)聽多個文件描述符(fd)。這個時候C同學來裝水,發(fā)現(xiàn)有一排水龍頭,舍管阿姨告訴他這些水龍頭都還沒有水,等有水了告訴他。于是等啊等(select調(diào)用中),過了一會阿姨告訴他有水了,但不知道是哪個水龍頭有水,自己看吧。于是C同學一個個打開,往杯子里裝水(recv)。這里再順便說說鼎鼎大名的epoll(高性能的代名詞啊),epoll也屬于IO復用模型,主要區(qū)別在于舍管阿姨會告訴C同學哪幾個水龍頭有水了,不需要一個個打開看(當然還有其它區(qū)別)。
4、信號驅(qū)動IO模型
通過調(diào)用sigaction注冊信號函數(shù),等內(nèi)核數(shù)據(jù)準備好的時候系統(tǒng)中斷當前程序,執(zhí)行信號函數(shù)(在這里面調(diào)用recv)。D同學讓舍管阿姨等有水的時候通知他(注冊信號函數(shù)),沒多久D同學得知有水了,跑去裝水。是不是很像異步IO?很遺憾,它還是同步IO(省不了裝水的時間啊)。
5、異步IO模型
調(diào)用aio_read,讓內(nèi)核等數(shù)據(jù)準備好,并且復制到用戶進程空間后執(zhí)行事先指定好的函數(shù)。E同學讓舍管阿姨將杯子裝滿水后通知他。整個過程E同學都可以做別的事情(沒有recv),這才是真正的異步IO。
一般來講:阻塞IO模型、非阻塞IO模型、IO復用模型(select/poll/epoll)、信號驅(qū)動IO模型都屬于同步IO,因為階段2是阻塞的(盡管時間很短)。只有異步IO模型是符合POSIX異步IO操作含義的,不管在階段1還是階段2都可以干別的事。
關于如何淺析編程語言中的五種編程模型就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。