1. 程式人生 > >同步、非同步、堵塞、非堵塞和函式呼叫及I/O之間的組合概念

同步、非同步、堵塞、非堵塞和函式呼叫及I/O之間的組合概念

        在我們工作和學習中,經常會接觸到“同步”、“非同步”、“堵塞”和“非堵塞”這些概念,但是並不是每個人都能將它們的關係和區別說清楚。本文將對這些基本概念進行討論,以期讓大家有更清楚的認識。(轉載請指明出於breaksoftware的csdn部落格)

        IT技術和相關術語均為舶來品,於是其相關的問題也並非只有我們講中文的分不清。在一些外文網站上,我們可以發現外國人也會對這些概念進行區分和探討。於是,我覺得通過一些英文資料來解釋這些問題比較合適,畢竟從語言的角度說,它們更貼近問題的起源。

        對於資料的選擇,我優先選擇相信大家公認的一些權威資料。比如RFC標準是最高的;其次是一些權威專家的論著,比如Addison Wesley的《UNIX Network Programming》;再其次是一些權威網站上的資訊,比如百度百科、維基百科、IBM或者微軟官網上一些論述。

        為了把問題說清楚,我決定先去探討意思相對的概念。比如“同步”和“非同步”就是相對的概念,因為我們從來不會說這是一個“同步非同步……”;同樣“堵塞”和“非堵塞”也是一對相對的概念,我們也不會說那是一個“堵塞非堵塞……”。然後我們將探討這兩對相對的概念的區別,比如“同步”和“堵塞”的區別,“非同步”和“非堵塞”的區別。最後我們將結合“函式呼叫”和“I/O”來探討組合出的概念。

同步/非同步

同步

        “同步”這個概念的探討將非常有意思,因為我們從這個詞可以感受下外語翻譯成中文後產生的偏差。
        現在我們先“忘記”自己是IT從業人員,“同步”對我們來說可以按

百度百科中的解釋為:

同步指兩個或兩個以上隨時間變化的量在變化過程中保持一定的相對關係。

        怎麼具體化這個解釋呢?比如戰爭中,一個集團軍的統帥命令自己部下左、中、右三軍“同步”前進。於是我們補腦一下,可以想象出同在一個時間段內,三個不同的個體在同時做三件事,而這三個個體存在一定的關聯性——同時聽命於集團軍的統帥。於是這就產生了一種混亂,當我們學習了IT技術,特別是瞭解了“執行緒”概念後,可能馬上把集團軍的統帥想成一個“程序”,而三個“同步”前進的軍隊就是三個“執行緒”。那麼此時“同步”是不是就是指若干個個體同時發生變化且存在一定關聯性呢?是不是更像“Asynchronous”的概念?其實這個問題並非我的臆測,之前在學校時,經常有同學將“同步”的概念理解成“Asynchronous”的行為特點,而我也曾被它們弄混淆過。
        雖然我沒有去考證過,但是我覺得上面對“同步”的解釋更加符合普通民眾的認知。
        然後不知何時“Synchronization”也被翻譯成“同步”了。於是我們在百度百科裡看到如下的解釋

    同步(英語:Synchronization),指對在一個系統中所發生的事件(event)之間進行協調,在時間上出現一致性與統一化的現象。在系統中進行同步,也被稱為及時(in time)、同步化的(synchronous、in sync)。

        其實這段解釋和維基百科中對“Synchronization”解釋是一致的

    Synchronization is the coordination of events to operate a system in unison. The familiar conductor of an orchestra serves to keep the orchestra in time. Systems operating with all their parts in synchrony are said to be synchronous or in sync; those which are not are asynchronous.

        這個解釋並不是我們關注的重點,因為它和我們探討的重心沒太多關係。我引入它只是為了說明“Synchronization”也被翻譯成“同步”這樣一件事的存在。

        然而,維基百科裡還有一段關於計算機術語中“Synchronization”的解釋,它被拿到一個單獨的頁面中解釋——足以說明它和傳統意義上“Synchronization”的不同

    In computer science, synchronization refers to one of two distinct but related concepts: synchronization of processes, and synchronization of data. Process synchronization refers to the idea that multiple processes are to join up or handshake at a certain point, in order to reach an agreement or commit to a certain sequence of action. Data synchronization refers to the idea of keeping multiple copies of a dataset in coherence with one another, or to maintain data integrity. Process synchronization primitives are commonly used to implement data synchronization.

        這段解釋將“同步”分為兩種:資料同步和過程同步。資料同步不是我們討論的重點,所以忽略。過程同步(至於此處翻譯成“程序”還是“過程”,我覺得“過程”所以可以更加寬泛些而且合理,所以選用“過程”一詞)是指多個過程通過一定組織方式達到某種協調,這種協調包含“按一定順序執行”。這種解釋就非常像我們IT民工理解中的“synchronous”了。可惜漢語中“同步”至少在字面上是沒有這層意思的。

非同步

       “非同步”這個詞在漢語中應該沒有歷史包袱,所以它的表意和英語中“asynchronous”一致。於是沒什麼好討論的。唯一有意思的是這個詞是如何被選中來表示“asynchronous”的。可能是因為“synchronous”和“asynchronous”在英語中意思相反,而中文中已經找到“同步”來翻譯“synchronous”,於是取“同”相反的修飾詞“異”來翻譯“asynchronous”為“非同步”。
        在維基百科上,我找到“Asynchrony”一詞的解釋,其含義可以解釋“asynchronous”

    Asynchrony, in computer programming, refers to the occurrence of events independently of the main program flow and ways to deal with such events. These may be "outside" events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results

堵塞/非堵塞

堵塞

        堵塞(Blocking)在維基百科中的解釋如下:

    In computing, a process is an instance of a computer program that is being executed. A process always exists in exactly one process state. A process that is blocked is one that is waiting for some event, such as a resource becoming available or the completion of an I/O operation.

        其意思是過程需要等待一個事件的變化而處於某個狀態中。這個事件可以是個資源,比如:記憶體、CPU、網路、磁碟等

    In a multitasking computer system, individual tasks, or threads of execution, must share the resources of the system. These resources might be:
	• the CPU
	• network
	• memory
	• disk        

非堵塞

        我在維基百科上沒有找到“非堵塞(Non-blocking)”的詞條,但是找到一個類似的“Non-blocking algorithm

In computer science, an algorithm is called non-blocking if failure or suspension of any thread cannot cause failure or suspension of another thread

同步/非同步和堵塞/非堵塞

        假如我們只有上述知識,還是很難將“同步”和“堵塞”分清楚,也不太能說清“非同步”和“非堵塞”的區別。目前我看國內很多論壇上關於這個問題的討論也顯得前後矛盾。

        為了把概念區分開,我們可以借鑑下Addison Wesley的《UNIX Network Programming》中關於同步I/O和非同步I/O的一個討論:

        Synchronous I/O versus Asynchronous I/O
        POSIX defines these two terms as follows:
        A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
        An asynchronous I/O operation does not cause the requesting process to be blocked.
        Using these definitions, the first four I/O modelsblocking, nonblocking, I/O multiplexing, and signal-driven I/Oare all synchronous because the actual I/O operation (recvfrom) blocks the process. Only the asynchronous I/O model matches the asynchronous I/O definition.

        其大意是“同步I/O”要求過程堵塞直到I/O操作完成。後面我們會講到,即使使用O_NONBLOCK修飾的I/O,也會因為在呼叫read等函式時,需要等待核心層把讀取的資料運輸到使用者層。於是I/O操作的完成(completes)與否要視資料是否全部進入使用者層。

        也就是說“同步”強調的是操作最終完成了,而非中間狀態。“堵塞”強調的是對系統資源的等待。相應的,“非同步”強調的是操作沒有完成,處於中間狀態。“非堵塞”強調的是沒有對系統資源產生等待行為。之後我們將結合他們和“函式呼叫”及“I/O”的組合概念來加以區分。

同步/非同步、堵塞/非堵塞和函式呼叫

         以下圖為例,1、2的操作我們可以認為是“非堵塞的”,我們稱之為“非堵塞呼叫”或者“非同步呼叫”;3操作需要把資料從核心態運送到使用者態,於是發生資源等待,從而發生堵塞,我們可以稱之為“堵塞呼叫”或者“同步呼叫”(整個操作完成)。以更高的視角來看,1、2和3這一組操作最終達到的是一個“同步呼叫”的結果。


        可見“同步呼叫”是由“堵塞的呼叫”和“非堵塞的呼叫”組成,其過程可以沒有“非堵塞的呼叫”,但是必須至少有一個“堵塞的呼叫”。而“非同步呼叫”和“非堵塞呼叫”則可以視為一個意思。

同步/非同步、堵塞/非堵塞和I/O

 堵塞I/O       

        堵塞I/O是預設的I/O型別,因為它不需要使用O_NONBLOCK去修飾。以I/O讀取為例,在使用者態read函式會一直等待核心態返回結果。這種模型還可稱為“同步堵塞模型”

非堵塞I/O

        非堵塞I/O需要使用O_NONBLOCK去修飾。這樣在操作該I/O時,如果系統尚未將資料準備好,則直接從核心態返回一個錯誤。如果資料準備好了,則使用者態會等待核心將資料輸送到使用者態。這種模型可以稱之為“同步非堵塞模型”,因為從整個操作來看,這是個同步I/O。而從IO自身來看,因為被O_NONBLOCK修飾,所以是非堵塞的。

多路複用I/O

        不管I/O是否被O_NONBLOCK修飾,遇到select/poll方法都會被堵塞。所以多路複用I/O可以是“同步堵塞模型”,也可以是“同步非堵塞模型”

        但是在《Boost application performance using asynchronous I/O》一文(後稱《Boo》文)中,將使用O_NONBLOCK修飾的多路複用模型稱之為“Asynchronous blocking I/O”,這個觀點我是不認可的。

        為什麼呢?當我們定義一個名稱時,前面的定語可能用於修飾不同的概念。如果按照《Boo》文描述,Asynchronous應該是用於修飾I/O的,Blocking是用於修飾Select函式呼叫的。但是之前我們講過,Addison Wesley根據RFC對Synchronous I/O的定義,認定多路複用I/O不屬於非同步IO。同樣,如果Asynchronous不是修飾I/O,那麼Blocking是用於修飾I/O的麼?那當然更不對,因為I/O被O_NONBLOCK修飾了。那如果Asynchronous和Blocking都不是修飾I/O的,那麼Asynchronous blocking I/O和Synchronous non-blocking I/O又有什麼區別呢?

非同步I/O

        這種I/O在Linux系統上叫AIO,在windows系統上交IOCP(完成埠)。這種模型最大的特徵執行使用者態響應前,資料已經進入使用者態,從而不會發生像同步I/O一樣,需要等待核心態往使用者態輸送資料。這種模型也稱“非同步非堵塞模型”

        
參考連結: