linux同步與非同步
1. 請你談談關於IO同步、非同步、阻塞、非阻塞的區別
同步(synchronous)IO和非同步(asynchronous)IO,阻塞(blocking) IO和非阻塞(non-blocking)IO的區別是什麼?本文將從linux環境下的network IO背景出發,參考Richard Stevens的「UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking」中的相關內容,詳細解釋這四種IO模型的特點和區別。
在深入討論之前,重要的是明確本文的討論上下文為Linux環境下的network IO。
根據Richard Stevens的解釋,本文將對比五種IO模型,而由於信號驅動IO在實際應用中不常用,本文將僅討論剩下的四種:同步(synchronous)IO、非同步(asynchronous)IO、阻塞(blocking)IO和非阻塞(non-blocking)IO。
在network IO過程中,涉及的對象主要有兩個:一個是由用戶進程調用IO操作的系統對象(如進程或線程),另一個是系統內核(kernel)。一個read操作通常會經歷兩個階段:准備數據階段和拷貝數據階段。
接下來,我們將依次介紹這四種IO模型的特點和區別。
阻塞(blocking)IO
在Linux中,默認情況下,所有的socket都是阻塞的。一個典型的讀操作流程如下:用戶進程調用recvfrom系統調用時,內核開始准備數據階段。如果數據尚未到達,內核將進入等待狀態,而用戶進程同樣會被阻塞。當數據准備完畢後,內核將數據從內核復制到用戶內存中,然後返回結果,用戶進程解除阻塞狀態,重新執行。
因此,阻塞IO的主要特點是在兩個階段均被阻塞。
非阻塞(non-blocking)IO
在Linux環境下,可以通過設置socket使其變為非阻塞。當對一個非阻塞socket執行讀操作時,流程如下:如果內核中的數據尚未准備好,它不會阻塞用戶進程,而是立即返回錯誤。用戶進程在發起read操作後,不需要等待,立刻得到結果。用戶進程判斷結果為錯誤時,知道數據還未准備好,可以再次發送read操作。一旦數據准備完畢並再次收到系統調用,內核將數據復制到用戶內存並返回。
用戶進程需要主動詢問內核數據是否准備就緒。
IO多路復用(IO multiplexing)
IO多路復用(如select或epoll)允許單個進程同時處理多個網路連接的IO。其基本原理是內核持續監視所有連接,一旦有數據到達,就通知用戶進程。流程如下:用戶進程調用select時,整個進程被阻塞,而內核則監視所有select負責的socket。當任何一個socket的數據准備好時,select返回。用戶進程再次調用read操作,從內核復制數據到用戶進程。
與阻塞IO相比,多路復用IO需要兩次系統調用(select和recvfrom),而不是一次。然而,其優勢在於能同時處理多個連接。
需要注意的是,實際應用中,即使使用多路復用IO,通常也設置每個socket為非阻塞,但進程被select函數阻塞,而非被socket IO阻塞。
非同步(asynchronous)IO
Linux下的非同步IO應用較少。其流程如下:用戶進程發起read操作後,立即開始執行其他任務。另一方面,內核收到非同步讀請求後,立即返回,不阻塞進程。內核等待數據准備完成,將數據復制到用戶內存中後,通過發送信號通知用戶進程讀操作已完成。
非同步IO的主要區別在於:在執行IO操作時不會阻塞進程,直到內核發送信號通知操作完成。
這四種IO模型之間的主要區別在於阻塞與非阻塞、同步與非同步以及處理方式的不同。非阻塞IO允許進程在數據未准備好時繼續執行,而阻塞IO則需要等待操作完成。同步IO在執行過程中會阻塞進程,而非同步IO則在執行後立即返回,直到完成時通知進程。
2. 請問linux下C編程多線程同步和非同步的區別,如何能實現程序的同步和非同步編程
同步就是使得兩個或者多個進程之間的行為按照一定的時序來執行。比如說線程A完成了某件事,然後線程B才能做某件事。具體一點,就是,線程間的某個動作執行前需要確認一個或者多個其他線程的當前狀態。而非同步則是多個線程各跑各的,互不幹涉。
Linux下的多線程實現由pthread庫提供,頭文件為pthread.h。多線程最重要的就是要保護好共享資源(用互斥體,mutex),尤其是非同步。代碼哥哥就不上了,這里關鍵的不是代碼的問題,也不是Linux、Windows的問題,重要的是概念的理解。哥們不妨先研究研究「生產者-消費者」這個常出現在教科書上的模型,這是一個典型的同步問題。就講這么多了,拜拜。