Posted on 2012-12-18 13:55
鑫龍 閱讀(415)
評論(0) 編輯 收藏 引用 所屬分類:
linux多線程專題
(注:這篇文章轉自網絡,雖然Linux從內核2.6開始,多線程已使用NPTL技術,但是這篇文章對我們理解多線程技術還是挺有用的)
Linux內核對多進程和多線程的支持方式:
線程機制支持并發程序設計技術,在多處理器上能真正保證并行處理。而在linux實現線程很特別,linux把所有的線程都當作進程實現。linux下線 程看起來就像普通進程(只是該進程和其他進程共享資源,如地址空間)。上述機制與Microsoft windows或是Sun Solaris實現差異很大。
Linux的線程實現是在核外進行的,核內提供的是創建進程的接口do_fork()。內核提供了兩個系統調用__clone()和fork(),最終都 用不同的參數調用do_fork()核內API。 do_fork() 提供了很多參數,包括CLONE_VM(共享內存空間)、CLONE_FS(共享文件系統信息)、CLONE_FILES(共享文件描述符表)、 CLONE_SIGHAND(共享信號句柄表)和CLONE_PID(共享進程ID,僅對核內進程,即0號進程有效)。當使用fork系統調用產生多進程 時,內核調用do_fork()不使用任何共享屬性,進程擁有獨立的運行環境。當使用pthread_create()來創建線程時,則最終設置了所有這 些屬性來調用__clone(),而這些參數又全部傳給核內的do_fork(),從而創建的”進程”擁有共享的運行環境,只有棧是獨立的,由 __clone()傳入。
即:Linux下不管是多線程編程還是多進程編程,最終都是用do_fork實現的 多進程編程,只是進程創建時的參數不同,從而導致有不同的共享環境。Linux線程在核內是以輕量級進程的形式存在的,擁有獨立的進程表項,而所有的創 建、同步、刪除等操作都在核外pthread庫中進行。pthread 庫使用一個管理線程(__pthread_manager() ,每個進程獨立且唯一)來管理線程的創建和終止,為線程分配線程ID,發送線程相關的信號,而主線程pthread_create()) 的調用者則通過管道將請求信息傳給管理線程。
很多朋友都說使用多線程的好處是資源占用少,其隱含之意就是說進程占用資源比線程多,對吧?但實際上Linux下多進程是否就真的點用很多資源呢? 暫且不說進程是否比線程占用資源多,就進程占用資源的多少情況而言,Linux確實是做得相當節省的。產生一個多進程時肯定是要產生的一點內存是要復制進 程表項,即一個task_struct結構,但這個結構本身做得相當小巧。其它對于一個進程來說必須有的數據段、代碼段、堆棧段是不是全盤復制呢?對于多 進程來說,代碼段是肯定不用復制的,因為父進程和各子進程的代碼段是相同的,數據段和堆棧段呢?也不一定,因為在Linux里廣泛使用的一個技術叫 copy-on-write,即寫時拷貝。copy-on-write意味著什么呢?意味著資源節省,假設有一個變量x在父進程里存在,當這個父進程創建 一個子進程或多個子進程時這個變量x是否復制到了子進程的內存空間呢?不會的,子進程和父進程使用同一個內存空間的變量,但當子進程或父進程要改變變量x 的值時就會復制該變量,從而導致父子進程里的變量值不同。父子進程變量是互不影響的,由于父子進程地址空間是完全隔開的,變量的地址可以是完全相同的。
Linux的”線程”和”進程”實際上處于一個調度層次,共享一個進程標識符空間,這種限制使得不可能在Linux上實現完全意義上的POSIX線程機 制,因此眾多的Linux線程庫實現嘗試都只能盡可能實現POSIX的絕大部分語義,并在功能上盡可能逼近。Linux進程的創建是非常迅速的。內核設計 與實現一書中甚至指出Linux創建進程的速度和其他針對線程優化的操作系統(Windows,Solaris)創建線程的速度相比,測試結果非常的好, 也就是說創建速度很快。由于異步信號是內核以進程為單位分發的,而LinuxThreads的每個線程對內核來說都是一個進程,且沒有實現”線程組”,因 此,某些語義不符合POSIX標準,比如沒有實現向進程中所有線程發送信號,README對此作了說明。LinuxThreads中的線程同步很大程度上 是建立在信號基礎上的,這種通過內核復雜的信號處理機制的同步方式,效率一直是個問題。LinuxThreads 的問題,特別是兼容性上的問題,嚴重阻礙了Linux上的跨平臺應用(如Apache)采用多線程設計,從而使得Linux上的線程應用一直保持在比較低 的水平。在Linux社區中,已經有很多人在為改進線程性能而努力,其中既包括用戶級線程庫,也包括核心級和用戶級配合改進的線程庫。目前最為人看好的有 兩個項目,一個是RedHat公司牽頭研發的NPTL(Native Posix Thread Library),另一個則是IBM投資開發的NGPT(Next Generation Posix Threading),二者都是圍繞完全兼容POSIX 1003.1c,同時在核內和核外做工作以而實現多對多線程模型。這兩種模型都在一定程度上彌補了LinuxThreads的缺點,且都是重起爐灶全新設 計的。
綜上所述的結論是在Linux下編程多用多進程編程少用多線程編程。
IBM有個家伙做了個測試,發現切換線程context的時候,windows比linux快一倍多。進出最快的鎖(windows2k的 critical section和linux的pthread_mutex),windows比linux的要快五倍左右。當然這并不是說linux不好,而且在經過實際 編程之后,綜合來看我覺得linux更適合做high performance server,不過在多線程這個具體的領域內,linux還是稍遜windows一點。這應該是情有可原的,畢竟unix家族都是從多進程過來的,而 windows從頭就是多線程的。
如果是UNIX/linux環境,采用多線程沒必要。
多線程比多進程性能高?誤導!
應該說,多線程比多進程成本低,但性能更低。
在UNIX環境,多進程調度開銷比多線程調度開銷,沒有顯著區別,就是說,UNIX進程調度效率是很高的。內存消耗方面,二者只差全局數據區,現在內存都很便宜,服務器內存動輒若干G,根本不是問題。
多進程是立體交通系統,雖然造價高,上坡下坡多耗點油,但是不堵車。
多線程是平面交通系統,造價低,但紅綠燈太多,老堵車。
我們現在都開跑車,油(主頻)有的是,不怕上坡下坡,就怕堵車。
高性能交易服務器中間件,如TUXEDO,都是主張多進程的。實際測試表明,TUXEDO性能和并發效率是非常高的。TUXEDO是貝爾實驗室的,與UNIX同宗,應該是對UNIX理解最為深刻的,他們的意見應該具有很大的參考意義注:關于那個critical section和pthread_mutex_t,critical section本質上是一個自旋鎖,短期鎖當然快,要比也該是和pthread_spinlock_t比。
mutex和critical section的確是不能比的。一個涉及到內核,一個沒有涉及到內核。
轉自http://www.soft-bin.com/html/2010/07/09/%E5%A4%9A%E8%BF%9B%E7%A8%8Bvs%E5%A4%9A%E7%BA%BF%E7%A8%8B%EF%BC%8C%E4%B8%80%E4%B8%AA%E9%95%BF%E6%9C%9F%E7%9A%84%E4%BA%89%E8%AE%BA.html,貌似他也是轉別人的。 轉自:
http://blog.chinaunix.net/uid-20556054-id-3068371.html