資源描述:
《Linux下多線程并發(fā)控制的機制分析》由會員上傳分享,免費在線閱讀,更多相關內容在教育資源-天天文庫。
1、Linux下多線程并發(fā)控制的機制分析一、Linux下并發(fā)控制原因及方法1.1、并發(fā)控制如果在對linux字符設備驅動實例進行分析時,我們可能會有一個疑問,當我們調用copy_to_user和copy_from_user函數(shù)完成從用戶態(tài)、內核態(tài)的讀寫操作的時候,如果這兩個操作并發(fā)執(zhí)行的話會出現(xiàn)一個什么樣的情況?那肯定是會出現(xiàn)問題的,這個很容易理解,那么我們怎么去解決這一類似的問題呢?這就是我現(xiàn)在要探討的linux并發(fā)控制機制。我們在設備驅動的編寫過程中要解決的一個問題就是并發(fā)的控制,也就是進程對共享資源的并發(fā)訪問,而在linux中,提供了多個解決并發(fā)控制的方式,比如:中斷屏蔽、原子操作、互
2、斥鎖等,下面將逐一介紹。1.2、中斷屏蔽中斷屏蔽的概念實際上就是平常所說的開中斷、關中斷。在單cpu中使用中斷屏蔽來避免竟態(tài)是很方便的一種方法,每次在進入臨界區(qū)之前屏蔽所有的中斷,訪問完成后再打開中斷。這項功能可以保障在執(zhí)行的內核執(zhí)行路徑不被中斷處理程序所搶占。它將使得中斷與進程之間的并發(fā)不在發(fā)生,而且由于linux內核的進程調度都依賴于中斷來實現(xiàn),所以這樣也就可以避免進程之間的并發(fā)。中斷對于內核的運行是非常重要的,在中斷屏蔽期間,所有的中斷都無法得到處理,因此長時間的屏蔽中斷是很危險的,可能會造成數(shù)據(jù)丟失、系統(tǒng)崩潰等嚴重的后果。這就要求臨界區(qū)的執(zhí)行應該盡可能的快。1.3、原子操作原子操
3、作,指的是在執(zhí)行的過程中不會被中斷的操作。linux內核提供了一系列的函數(shù)來完成原子操作,內核代碼可以安全的調用他們而不被打斷。1.4、自旋鎖-12-自旋鎖是一種典型的互斥訪問臨界資源的手段。為何叫自旋鎖,還得從他的工作機制說起。為了獲得一個自旋鎖,在cpu上運行的代碼需要先執(zhí)行一個原子操作,該操作測試并設置某個內存變量,而且在操作完成之前無法被打斷,即別的執(zhí)行單元是不能訪問這個內存變量的。當測試結果表明鎖已空閑,那么程序就獲得者個自旋鎖并繼續(xù)執(zhí)行它,如果測試表明鎖被占用,那么程序則一直重復測試操作直到鎖空閑為止,這就是自旋的概念。理解一個自旋鎖也不是很困難,我們可以把它當成一個變量來看
4、待,就像原子變量。比如兩個執(zhí)行單元A、B,如果A先進入,那么它將持有鎖,當B也想進入的時候,但是測試出鎖已經被占有,那么它將一直等待鎖被釋放后再進入。二、程序功能設計為了研究Linux下的多線程機制,設計生產者和消費者研究程序,程序結構如下圖所示:圖1.1程序結構圖主線程負責創(chuàng)建生產者線程和消費者線程。主線程同時還負責觀察產品倉庫的情況,它每5秒查看一次倉庫的大小和剩余產品。生產者線程在啟動以后,負責生產產品,并且往產品倉庫里面放。消費者線程在啟動以后,負責消費產品,從產品里面取出產品。-12-當生產者線程把產品倉庫放滿以后,就不再生產產品,而是等待消費者取走產品后再生產。消費者把倉庫取
5、空之后,就不再從倉庫中取產品,而是等待生產者生產產品后再取。三、程序實現(xiàn)環(huán)境:操作系統(tǒng):RHEL5,語言:C++。在Linux中,使用Pthread庫來操作線程。POSIXthread是一個標準線程定義,該標準定義一系列的多線程標準。pthreads線程庫實現(xiàn)了POSIX線程標準,定義了一套CC++語言下的線程庫。首先需要定義生產者線程、消費者線程、產品倉庫等,在本例中,使用pthread線程庫,所以生產者線程和消費者線程都定義為pthread_t類型;產品倉庫則使用一個先進先出的隊列來實現(xiàn),這個隊列類型直接使用了stl庫中的list結構。//定義生產者和消費者線程pthread_tp
6、roducer,consumer;//定義產品倉庫,用List結構來保存。liststoreList;在主線程中使用pthread_create方法來創(chuàng)建了生產者線程和消費者線程,創(chuàng)建線程主要需要傳入pthread_t類型的線程對象,以及線程的工作方法。如果線程創(chuàng)建函數(shù)返回的值不為0,則表示線程創(chuàng)建失敗,可能由于沒有足夠的系統(tǒng)資源。//創(chuàng)建生產者線程,并使其工作。ret=pthread_create(&producer,NULL,producer_work,NULL);//創(chuàng)建消費者線程,并使其工作。ret1=pthread_create(&consumer,NULL,cons
7、umer_work,NULL);//如果線程創(chuàng)建函數(shù)返回的值不為0,則表示線程創(chuàng)建失敗,可能由于沒有足夠的系統(tǒng)資源。if(ret!=0
8、
9、ret1!=0){cout<<"創(chuàng)建線程錯誤!";exit(1);}-12-在生產者線程的工作代碼(producer_work方法)中,首先用死循環(huán)來保證它一直在工作,每一次的工作邏輯如下:a.判斷倉庫大小,如果倉庫未滿,則往倉庫里放入產品。b.放完產品以后,判斷消費者線程是否在睡眠狀態(tài),如果