全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1736
推到 Plurk!
推到 Facebook!

同步 異步 阻塞 不塞 之我見

 
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2015-01-07 15:23:06 IP:114.32.xxx.xxx 訂閱


有朋友看了我的socket同步與阻塞的文後,對我challenge一下,他說:

根據wikipedia說,同步io就是blocking io的另一種說法,所以即然同步了,哪來的「同步又非阻塞」。這問題好,我喜歡被challenge,順便檢驗自己的所學是否有遺漏,正所謂教學相長就是這道理了。 :)

我回他說:

若下雨,則帶傘。

那麼帶傘一定下雨?

不一定嘛,帶陽傘是一種可能,娶新娘時也不一定在下雨,是吧!

他說,然後呢? 這表示什麼?

我慢慢的說,要仔細聽好了,因為會感覺莊子論魚、白馬非馬的論調。首先,我們要對問題做一些定義,不然很難有共識。

同步與異步 (注意,我不是講同步xx,我只講同步(二個字)、異步(二個字),它所表達的只是一種同時間,或不同時間… (他想打我)。我繼續說,比如同步可以是通訊的「同步傳輸」,也可以是講程式上的「同步io」,也可以講「二條thread間,無關io的thread的同步」,還有…同步吃便當……,不過不管如何,都有一個很重要的相同處,「同步討論的一定是有二個主體」,比如「同步吃便當」,你能想像某人說他在同步與某吃便當,但旁邊沒人嗎? 是阿飄嗎? XD

鳴~~好啦,到底意思要表達什麼? 他說。我要表達的就是,我們要先界定「誰與誰同步」。開始要進入程式的角度了,請座好。程式大致可分為kernel mode 與 user mode下的程式。通常我們說「同步io」,我們在意的是「kernel的某thread與user的某thread間,io的傳遞」。當然,你也可以說,那我的應用程式開二條thread,二條間buffer copy來copy去,可不可以也叫討論「同步io」? 當然可以,但關於效能,這種討論意義較小。io 通常是週邊裝備與kernel間在傳輸,然而現代作業系統都會用保護模式,來避免一般應用程式直接與週邊io。也因此,io都是 kernel api 與 user api間傳遞,這相當耗時耗資源。所以我才會說「同步io」要界定在「某kernel thread 與 user thread間」的問題。

(喝水)。那阻塞呢? 它也是普通形容詞/名詞,主要就是說塞住了… (我又癈話了…)。我沒癈話喔,我主要要表達的是,阻塞所關心的是「接下來的程式或是函式」會不會塞住。它並不關心「別人」是如何。這與「同步」考慮的是二個主體是不一樣的。以 socket api來說,當我把socket設定成 block。它代表的是…

接下來使用的api,比如recv,send等這些windows提供的user api一呼叫就會塞住。我們不清楚kernel與user間是怎麼個io法,我就只是知道呼叫它就會塞住…動不了。

所以,會塞與「同步io」沒有一定的關連。朋友聽了馬上回…難道「同步io」不會塞? 不會塞會叫「同步」? 啊~~對,這就是直叫人搞不清楚的地方了。我說:

同步io至少1條thread會塞(呼叫者),但會塞不一定是「同步的io」。一如一開始我說的,下雨帶傘。帶傘又不一定下雨。

因此,我先把結論和你說,比如把socket設成none-block,接著用recv就不會塞了。「但你依然不能確定kernel與recv間到底是怎麼個io法」。因為 recv 這個USER mode api是微軟的人員寫的,他沒交待裡面是怎麼實作的。假如我是微軟的人來寫這個api,我可以這樣來寫(假碼,別計較精準): new thread(read()); if(noneBlock and no input) return WSAEWOULDBLOCK; 結束。然後我的read是會block住,並與kernel進行「同步」。 如此的話,你以為 recv 不塞,然後就是異步io,你就錯了!

「會塞不一定同步io,不會塞也不一定是異步io,塞不塞是使用的api問題,同步io與異步io則是api內部實作io傳遞的方式,表裡不一定要一致」。

進一步說,若我把不會塞的recv這個api再包到我自創的叫JiaHuiSai()裡面,然後我在JiaHuiSai裡寫 yiZhiRun = true; while(yiZhiRun) { CheckThenSetYiZhiRun()} ; 而你呼叫了我的JiaHuiSai(),你就塞了,你根本不知道事實上背後用的是「不會塞的recv」。

塞不塞也可以擴展到「下面的程式段塞不塞」的關係,不一定要是api本身。但依然關心的是「目前自己的主體」。塞不塞與 誰和誰同步 沒必然關係。

最後,你應該要問我,那到底如何知道哪個api是同步或異步? 看微軟的文件啊,他說某api是同步就是同步。比如socket下,設定overlapped等並用WSARecv...WSAxxxx,就會使得"內部"實作「異步」。至於普通的send,recv…這些api,就算是不塞,因為沒有帶入overlapped struct的能力,依然採「同步」處理io。

還要再來challenge嗎? 誠心歡迎… :)
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2015-01-07 15:24:21, 註解 無‧
aftcast 重新編輯於 2015-01-07 15:25:05, 註解 無‧
系統時間:2024-03-29 6:06:35
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!