国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

程序員自我修養雜記

2019-11-08 02:46:47
字體:
來源:轉載
供稿:網友

計算機 對于系統程序開發者來說,計算機三個部件最為關鍵:CPU、內存、I/O控制芯片。 高速的北橋芯片:為了協調CPU、內存和高速的圖形設備。此時慢速的I/O總線已經無法滿足需求。 低速設備的南橋芯片:由于北橋芯片運行速度非常高,于是人們有設計了低速設備的南橋芯片,磁盤、usb、鍵盤、鼠標等設備都連接在南橋芯片上,由南橋芯片將他們匯總后鏈接到北橋上。 SMP(對稱多處理器)多CPU的計算機;簡單的來講就是每個CPU在系統中所處的地位和發揮的功能是一樣的,是相互對稱的。使用場景:大型數據庫、網絡服務器上,他們要求同時處理大量的請求,而這些請求時相互獨立的,所以多處理器就可以最大效能的發揮作用。多處理器最多的應用場合時這些商用的服務器和需要處理大量計算的環境。(CPU頻率碰到了天花板4GHZ,才出現了SMP). 多核處理器:實際上就是SMP的簡化版。這是由于多處理器成本高,所以廠商將多個處理器“合并在一起打包出售”,這些被打包的處理器之間共享比較昂貴的緩存部件,只保留多個核心;并且以一個處理器的外包裝進行出售,價格比單核處理器只貴一點。當然他們在緩存共享方面有細微的差別,但是從程序員的角度來看,他們的區別很小,邏輯上看他們是完全相同的。 系統軟件:傳統意義上一般將用于管理計算機本身的軟件稱為系統軟件,以區別普通的應用程序。系統軟件可以分為兩塊;一塊是平臺性的,比如,操作系統內核、驅動程序、運行庫和數以千記得系統工具;另一塊是用于程序開發的,比如,編譯器、鏈接器、匯編器等開發工具和開發庫。 計算機系統軟件體系結構采用一種層的結構:計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決。 接口:每個層次之間都必須要相互通信,則需要一個通信協議,我們一般將其稱為接口。接口下面那層是提供者,上層是使用者。除了硬件和應用程序,其他層都是中間層,每個中間層都是對它下面的那層的包裝與擴展。正是由于這些中間層的存在,使得應用程序和硬件之間保持相對獨立。

在軟件體系結構中:位于最高層的是應用程序。從整個層次結構上來看,開發工具與應用程序屬于同一層,因為他們都使用同一接口,那就是操作系統應用程序編程接口。應用程序接口的提供者是運行庫。 運行庫使用操作系統提供的系統調用接口,系統調用接口往往以軟中斷的方式提供;比如,linux使用0x80號中斷作為系統調用接口。 硬件規格: 操作系統內核層對于硬件層來說是硬件接口的使用者,而硬件是接口的定義者,硬件的接口的定義決定了操作系統的內核,具體來講就是驅動程序如何操作硬件,如何與硬件通訊,這種接口被叫做硬件規格。

操作系統:一個功能是提供抽象的接口,另外一個主要功能就是管理硬件資源。 多道程序的設計:編寫一個監控程序,當某個程序暫時無需使用CPU時,監控程序就把另外的正在等待CPU資源的程序啟動起來,使得CPU能夠充分利用起來,這種被稱為多到程序。 分時系統:每個程序運行一段時間后都主動讓出CPU給其他的程序,使得一段時間內每個程序都有機會運行一小段時間。 多任務系統:操作系統接管了所有的硬件資源,并且本身運行在一個受硬件保護的級別,每個進程都有自己的獨立空間,使得進程之間的地址相互隔離。CPU由操作系統同一分配,每個進程都會根據進程優先級的高低都有機會得到CPU.但是,如果運行超出了一定的時間,操作系統會暫停該進程,將CPU資源分配給其他的等待運行的進程,這種CPU分配方式為搶占式。

驅動程序可以看做事操作系統的一部分,它往往和系統內核一起運行在特權級別,但他與操作系統內核之間有一定的獨立性,使得驅動程序有較好的靈活性。操作系統開發者為硬件生產商提供了一系列接口和框架,凡是按照這個接口和框架開發的驅動程序都可以在該操作系統上使用。進程的總體目標是希望每個進程從邏輯上看都可以獨占計算機的資源。操作系統的多任務功能使得CPU能夠在多個進程之間共享;從進程的角度看好像是他獨占了CPU而不用考慮與其他進程分享CPU的事。操作系統的I/O抽象模型也很好的實現I/O設備的共享和抽象。內存通過虛擬地址空間;分段分頁來實現共享。為什么要虛擬內存:如果程序直接在物理內存上使用,直接訪問物理地址將帶來很多問題:

1. 地址空間不隔離:所有程序都訪問物理地址,程序所使用的內存空間不相互隔離,惡意的程序可以很容易改寫其他程序的內存數據,以達到破壞的目的。有些非惡意、但有臭蟲的程序可能不小心修改ill其他程序的數據,就會使其他程序崩潰。而使用虛擬地址空間可保證一個任務的失敗不影響其他任務的執行。 2. 內存使用效率低:由于沒有有效的內存管理機制,通常需要一個程序執行時,監控程序就將整個程序裝載進內存然后執行。內存不夠時會發生大量的數據交換,效率低下。 3. 程序運行的地址不穩定:因為程序每次需要裝入運行時,我們都需要給他從內存中分配一塊足夠大的內存空間區域,這個區域位置不確定;這給程序的編寫造成一定的麻煩,因為程序在編寫時,它訪問的數據和指令跳轉時的目標地址很多都市固定的,這涉及到重定位問題。

解決問題的思路就是增加中間層,即使用一種間接地址訪問方法。我們把程序給出的地址看作是一種虛擬地址,然后通過某種映射,將虛擬地址轉換為物理地址。這樣,只要我們能夠妥善控制這個虛擬地址到物理地址的映射過程,就可以保證任意一個程序所能夠訪問的物理內存區域跟另一個程序相互不重疊,以達到地址空間隔離的效果。物理地址空間是真真實實存在的;虛擬地址空間是指虛擬的,而且每個進程只能訪問自己的地址空間,這樣就有效的做到了進程的隔離。

分段:解決了第一個和第三個問題。首先,它做到了地址的隔離,如果程序訪問越界,將會被硬件判斷為非法訪問,拒絕這個地址請求,并將這個請求報告給操作系統或者監控程序。再者,對于每個程序員來說,無論他們被分配到物理地址的那個區域,對于程序來說都是透明的。他們不需要關心物理地址的變化。 但分段沒有解決內存使用效率問題;分段對內存區域的映射還是按照程序為單位;如果內存不足,被換入換出到磁盤的都是整個程序,這樣勢必會造成大量的磁盤訪問操作,從而嚴重影響速度。這種方法換是顯得比較粗糙,粒度比較大。 事實上,根據程序的局部性原理,當一個程序在運行時,在某個段內,它只是頻繁的用到一小部分數據,也就是說,程序的很多數據其實在一段時間內都是不會被用到的。人們很自然的想到了更小粒度的內存分割和映射的方法,使得程序的局部性原理得到充分的利用,大大提高了內存使用率,這種方法就是分頁。 分頁:提高了內存的使用率,減少了內存碎片的產生;保護也是頁映射的目的之一。簡單來說就是每個頁可以設置權限屬性,只有操作系統有權限修改這些屬性。MMU都集成在CPU的內部了,不會以獨立的部件存在。

線程基礎 線程:有時被稱為輕量級的進程(LWP),是程序執行流的最小單位。一個標準的線程是由線程ID/當前指令指針(PC)、寄存器集合和堆棧組成。通常意義上,一個進程由一到多個線程組成,各個線程之間共享程序的內存空間(包括代碼段、數據段、堆等)以及一些進程級的資源(打開的文件和信號)。 使用多線程的原因: 1. 某個操作可能會陷入長時間的等待,等待的線程會進入睡眠狀態,無法繼續執行,多線程執行可以有效的利用等待的時間。典型的例子是等待網絡響應,這可能要花費數秒。 2. 某個操作(計算)會消耗大量的時間,如果只有一個線程,程序和用戶之間的交互會中斷。多線程可以讓一個線程負責交互,另一個線程負責計算。 3. 程序本身就要求并發操作。、 4. 多CPU或多核計算機,本身具備同時執行多個線程的能力,因此單個線程程序無法全面的發揮計算機的全部計算能力。 5. 相對于多進程應用,多線程在數據共享方面效率要高得多。

線程的訪問權限 線程的訪問非常自由,它可以訪問進程內存空間內的所有數據,甚至包括其他線程的堆棧(如果他知道其他線程的堆棧地址,這是很少見的情況),但實際運用中線程也擁有自己的私有存儲空間: 1. 棧:盡管并非完全無法被其他線程訪問,但一般情況下仍然可以認為是私有數據。 2. 線程局部存儲,是某些操作系統為線程單獨提供的私有空間,但通常只具有很有限的容量。 3. 寄存器:寄存器是執行流的基本數據,因此為線程私有。

從C程序員的角度看,數據在線程之間是否私有: 私有:局部變量、函數參數、TLS線程局部存儲數據 線程之間共享進程所有:全局變量、堆上的數據、函數里的靜態變量、程序代碼,任何程序都有權讀取并執行任何代碼、打開的文件。

線程調度:一個不斷在處理器上切換不同線程的的行為。線程通常至少擁有三種狀態:運行、就緒、等待。IO密集型線程:頻繁等待的線程;CPU密集型線程:很少等待的線程;IO密集型的線程總比cpu密集型的線程容易得到優先級的提升。對于linux來說,線程并不是一個通用的概念;linux對多線程支持頗為貧乏;事實上,在linux內核中并不存在真正意義上的線程的概念。Linux將所有可執行的實體稱為任務(TASK),無論是進程換是線程。每一個任務概念上都類似于一個單進程的線程,具有內存空間、執行實體、文件資源。不過,linux下不同任務之間可以選擇共享內存空間,因而在實際意義上,共享同一個內存空間的多個任務構成了一個進程,這些任務也就成為了這個進程里的線程。在linux下,用以下方法可以創建一個新的任務。

系統調用 作用 效果 fork 復制當前進程 新的任務啟動并和本任務一起從fork返回,本任務返回的是新任務的pid,新任務返回0。Fork速度非常快,因為采用了寫時復制。Fork只能產生本任務的鏡像。 exec 使用新的可執行映像覆蓋當前可執行映像 Fork+exec啟動別的新任務。 Clone 創建子進程并從指定位置開始執行 產生新的線程使用clone。從指定的位置開始執行,并且(可選)共享當前的內存空間和文件等。如此就可以在實際效果上產生一個線程。

線程安全 同步:為了避免多個線程同時讀寫同一個數據而產生不可預料的結果,我們需要將各個線程對同一個數據的訪問同步。所謂的同步,既是指在一個線程訪問數據未結束的時候,其他線程不得對同一個數據進行訪問。如此,對數據的訪問被原子化了。 同步的方式: 1. 鎖、 2. 二元信號量、(多元)信號量(對于允許多個線程并發訪問的資源,它是一個很好的選擇;一個初始值為n的信號量允許N個線程并發訪問。) 3. 互斥量:和二元信號量很類似,資源進同時只能被一個線程訪問。不同的是,信號量在整個系統可以被任意線程獲取并釋放。而互斥量則要求那個線程獲取了互斥量,那個線程就要負責釋放這個鎖。 4. 臨界區:是比互斥量更加嚴格的同步手段。把臨界區的鎖獲取稱為進入臨界區,釋放稱為離開臨界區。臨界區和互斥量與信號量的區別在于,互斥量和信號量在系統的任何進程里都是可見的,也就是說,一個進程創建了一個互斥量或者信號量,另一個進程試圖獲取該鎖是合法的。然而,臨界區的作用范圍僅限于本進程,其他進程無法獲取該鎖。除此之外,臨界區胡互斥量具有相同的性質。 5. 讀寫鎖:適用于讀頻繁寫少的情況。對于一段數據,多個線程同時讀取總是沒有問題的,寫時必須上鎖。 6. 條件變量:作用類似一個柵欄。線程有兩種操作,等待與喚醒。使用條件變量可以讓許多線程一起等待某個事件的發生,當時間發生時,條件變量被喚醒,所有的線程可以一起恢復執行。

可重入與線程安全 一個函數要被重入只有兩種情況:一是多個線程同時執行這個函數;二是函數自身調用自身。一個函數被重入表示這個函數沒有被執行完成,由于外部因素或者內部調用,又一次進入函數執行。一個函數可重入,表明函數重入后不會產生任何不良的后果。一個函數要成為可重入的,必須具有如下幾個特點: 1. 不使用任何(局部)靜態或全局的非const變量。 2. 不返回任何(局部)靜態或者全局的非const變量的指針。 3. 僅依賴于調用方提供的參數。 4. 不依賴任何單個資源的鎖。 5. 不調用任何可重入的函數。 可重入是并發的強力保障,一個可重入的函數可以在多線程環境下放心使用。

過度優化; Volatile關鍵字:一是阻止編譯器為了提高速度將一個變量緩存到寄存器中而不寫回;二是阻止編譯器調整volatile變量的指令順序。 Barrier:因為即使volatile可以阻止編譯器調整順序,也無法阻止CPU動態調度換序。現在并不存在可移植的阻止換序的方法。通常情況下是通過調用CPU提供的一條指令,這條指令被稱為barrier。它可以阻止cpu將該指令之前的指令交換到它之后,反之亦然。Barrier指令的作用類似于一個攔水壩,阻止換序穿透這個大壩。

三種線程模型 Windows和linux,都是在內核里提供線程的支持。內核線程,這里的內核線程和linux內核里的kernel_thread并不是一回事,它和我們之前討論的一樣,由多個處理器或調度器來實現并發。然而用戶實際使用的的線程不是內核線程,而是存在于用戶態的用戶線程。用戶線程并不一定在操作系統內核內對應著同樣數量的內核線程。 用戶態多線程庫的實現 一對一模型:用戶線程具有和內核線程一致的優點,線程之間的并發,是真正的并發。一個線程阻塞,其他線程不會受到影響。一對一模型可以讓多線程程序在多處理器的系統上有跟好的體現。一般直接使用API或系統調用創建的線程均為一對一的線程。 缺點:一是由于許多操作系統限制了內核線程的數量,因此一對一線程會讓用戶的線程數量受到限制。二是許多操作系統內核線程調度時,上下文切換開銷大,導致用戶線程的執行效率下降。 多對一模型:線程間的切換由用戶態的代碼來進行,線程切換的速度要快許多,但是一個用戶線程阻塞,那么所有線程都將無法執行,因此此時內核里的線程也隨之阻塞了。多對一模型的好處就是高效的上下文切換和幾乎無限制的線程數量。 多對多模型:一個用戶線程阻塞并不會使得所有用戶線程阻塞,因為此時還有別的線程可以被調度來執行。另外,多對多模型對用戶線程的數量沒有什么限制,在多處理器上,線程也能得到一定性能的提升。


上一篇:x86雜記

下一篇:程序員自我修養雜記

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 吴忠市| 邵东县| 凤阳县| 青龙| 利津县| 酒泉市| 富宁县| 巴林左旗| 金门县| 即墨市| 财经| 宁波市| 湘潭市| 信宜市| 东辽县| 黄大仙区| 绥德县| 汉川市| 广平县| 肥东县| 会宁县| 宕昌县| 城市| 德昌县| 偏关县| 托里县| 江华| 北碚区| 策勒县| 开远市| 桐梓县| 张家界市| 聂荣县| 湛江市| 彩票| 安多县| 巴林右旗| 三原县| 化德县| 奉贤区| 白银市|