當前位置:首頁 > 芯聞號 > 充電吧
[導讀]第10章 虛擬存儲器 關鍵詞:虛擬存儲器,動態(tài)存儲器分配,地址空間與多級頁表,空閑鏈表,伙伴系統(tǒng) 為了更加有效地管理存儲器并且少出錯,現代系統(tǒng)提供了一種對主存的抽象概念,叫做虛擬存儲器(VM)。虛

第10章 虛擬存儲器 關鍵詞:虛擬存儲器,動態(tài)存儲器分配,地址空間與多級頁表,空閑鏈表,伙伴系統(tǒng) 為了更加有效地管理存儲器并且少出錯,現代系統(tǒng)提供了一種對主存的抽象概念,叫做虛擬存儲器(VM)。虛擬存儲器是硬件異常、硬件地址翻譯、主存、磁盤文件和內核軟件的完美交互,它為每個進程提供了一個大的、一致的、私有地址空間。通過一個很清晰的機制,虛擬存儲器提供了三個重要的能力:它將主存看成是一個存儲在磁盤上的地址空間的高速緩存,在主存中保存活動區(qū)域,并根據需要在磁盤和主存之間來回傳送數據,通過這種方式,它高效地使用了主存;它為每個進程提供了一致的地址空間,從而簡化了存儲器管理;它保護了每個進程的地址空間不被其它進程破壞。 10.1 物理和虛擬地址 計算機系統(tǒng)的主存被組織成一個M個連續(xù)的字節(jié)大小的單元組成的數組。每字節(jié)都有一個唯一的物理地址(physical address,PA)。第一個字節(jié)的地址為0,接下來的字節(jié)地址為1,再下一個為2,以此類推。給定這種簡單的結構,CPU訪問存儲器的最自然的方式就是使用物理地址。我們把這種方式稱為物理尋址(physical addressing)。 早期的PC使用物理尋址,而且諸如數字信號處理器、嵌入式微控制器以及Cray超級計算機這樣的系統(tǒng)仍然繼續(xù)使用這種尋址方式及。然而,為通用設計的現代處理器使用的是虛擬尋址(virtual addressing)。 根據虛擬尋址,CPU通過生成一個虛擬地址(virtual address,VA)來訪問主存,這個虛擬地址在被送到存儲器之前先轉換成適當的物理地址。講一個虛擬地址轉換為物理地址的任務叫做地址翻譯(address translation)。就像異常處理一樣,地址翻譯需要CPU硬件和操作系統(tǒng)之間的緊密合作。CPU芯片叫做MMU(memory management unit,存儲器管理單元)的專用硬件,利用存放在主存中的查詢表來動態(tài)翻譯虛擬地址,該表的內容是由操作系統(tǒng)管理的。 10.2 地址空間 地址空間(address space)是一個非負整數地址的有序集合:{0,1,2……}。 如果地址空間中的整數是連續(xù)的,我們說它是一個線性地址空間(linear address space)。為了簡化討論,總是假設使用的是線性地址空間。在一個帶虛擬存儲器的系統(tǒng)中,CPU從一個有N=2^n個地址的空間中生成虛擬地址,這個地址空間被稱為虛擬地址空間(virtual address space):{0,1,2,……,N-1}。 一個地址空間的大小是由表示最大地址所需要的位數來描述的。例如,一個包含N=2^n個地址的虛擬地址空間就叫做一個n位地址空間。 一個系統(tǒng)還有一個物理地址空間(physical?address space),它與系統(tǒng)中物理存儲器的M個字節(jié)相對應:{0,1,2,……,M-1}。 10.3 虛擬存儲器作為緩存的工具 1 虛擬存儲器基本概念 虛擬存儲器被組織為一個由存放在磁盤上的N個連續(xù)的N個連續(xù)的字節(jié)大小的單元組成的數組。每字節(jié)都有一個唯一的虛擬地址,這個唯一的虛擬地址是作為到數組的縮印的。磁盤上數組的內容被緩存在主存中。和存儲器層次結構中的其它緩存一樣,磁盤(較低層)上的數據被分割成塊,這些塊作為磁盤和主存(較高層)之間的傳輸單元。VM系統(tǒng)通過將虛擬存儲器分割為稱為虛擬也(virtual page,VP)的大小固定的塊,來處理這個問題。每個虛擬頁的大小為P=2^p字節(jié)。類似地,物理存儲器被分割為物理頁(physical page,PP),大小也為P字節(jié)(物理頁也被稱為頁幀,page frame)。 在任何時刻,虛擬頁面的集合都分為三個不相交的子集: 未分配的:VM系統(tǒng)還未分配(或者創(chuàng)建)的頁。未分配的塊沒有任何數據和它們相關聯(lián),因此也就不占用任何磁盤空間。 緩存的:當前緩存在物理存儲器中的已分配頁。 未緩存的:沒有緩存在物理存儲器中的已分配頁。 2 DRAM高速緩存的組織結構 在存儲器層次結構中,DRAM緩存的位置對它的組織結構有很大的影響。回想一下:DRAM比SRAM要慢大約10倍,而磁盤要比DRAM慢大約100 000多倍。因此DRAM緩存中的不命中比起SRAM緩存中的不命中要昂貴的多,因為DRAM緩存不命中要由磁盤來服務,而SRAM緩存不命中通常是由基于DRAM的主存來服務的。而且,從磁盤的一個山區(qū)讀取第一字節(jié)的時間開銷比起讀這個扇區(qū)中后面的字節(jié)要慢大約100 000倍。歸根到底,DRAM緩存的組織結構完全是由巨大的不命中開銷驅動的。 因為大的不命中處罰和訪問第一字節(jié)的開銷,虛擬頁趨向于很大,典型地是4-8KB。由于大的不命中處罰,DRAM緩存是全相聯(lián)的,也就是說,任何虛擬頁都可以放置在任何的物理頁中。不命中時的替換策略也很重要,因為替換錯了虛擬頁的處罰也非常之高。因此,比起硬件對SRAM緩存,操作系統(tǒng)對DRAM緩存使用了更復雜精密的替換算法。最后,因為對磁盤的訪問時間很長,DRAM緩存總是使用寫回(write-back),而不是直寫(write-through)。 3 頁表 頁表將虛擬頁映射到物理頁。每次地址翻譯硬件將一個虛擬地址轉換為物理地址時,都會讀取頁表。操作系統(tǒng)負責維護也表的內容,以及在次番禺DRAM之間來回傳送頁。 頁面中的話,就可以直接引用數據,如果發(fā)生了也不命中,即缺頁,就需要進行頁面調度。常用的方法有按需頁面調度。 盡管在整個運行過程中引用的不同頁面的綜述可能超出物理存儲器總的大小,但是局部性原則保證了在任意時刻,這些頁面將趨向于在一個較小的活動頁面(active page)集合上工作,這個集合叫做工作集(working set)或者常駐集合(resident set)。在初始開銷,也就是將工作頁面調度到存儲器中,之后,接下來對這個工作集的引用將導致命中,而不會產生額外的磁盤流量。 只要我們的程序有良好的局部性,虛擬存儲器系統(tǒng)就能工作的相當好。但是,當然不是所有的程序都能展現良好的時間局部性。如果工作集的大小超過了物理存儲器的大小,那么程序將產生一種不幸的狀態(tài),叫做顛簸(thrashing)。這時頁面將不斷換進換出。 10.4 虛擬存儲器作為存儲器管理工具 虛擬地址是一個有用的機制,因為它大大簡化了存儲器管理,并提供了一種簡單自然的保護存儲器的方法。 多個虛擬頁面可以映射到同一個共享的物理頁面上。 虛擬存儲器作用: 簡化鏈接:獨立的地址空間允許每個進程為它的存儲器映像使用相同的基本格式,而不管代碼和數據實際存放在物理存儲器的何處。 簡化共享:獨立地址空間為操作系統(tǒng)提供了一個管理用戶進程和操作系統(tǒng)自身之間共享的一致機制。一般而言,每個進程都有自己私有的代碼、數據、堆以及棧區(qū)域,是不和其它進程共享的。在這種情況下,操作系統(tǒng)創(chuàng)建頁表,將相應的虛擬頁映射到不同的物理頁面。操作系統(tǒng)通過將不同進程中的適當的虛擬頁面映射到相同的物理頁面,從而安排多個進程共享這部分代碼的一個拷貝。 簡化存儲器分配:虛擬存儲器為用戶進程提供一個簡單的分配額外存儲器的機制。 簡化加載:虛擬存儲器也使加載可執(zhí)行文件和已共享目標文件到存儲器中變得容易。映射一個連續(xù)虛擬頁面的集合到任意一個文件中的任意一個位置的概念叫做存儲器映射(memory mapping)。 10.5 地址翻譯 PTE:頁表條目 多級頁表:第一,如果一級頁表中的一個PTE是空的,那么相應的二級頁表就不會存在。這表現出一種巨大的潛在節(jié)約,因為對于一個典型的程序,4GB的虛擬地址空間的大部分都會是未分配的。第二,只有一級頁表才需要總是在主存中。虛擬存儲器系統(tǒng)可以在需要時創(chuàng)建,并頁面調入或調出二級頁表,這就減少了主存的壓力。只有最經常使用的二級頁表才需要緩存在主存中。 10.6 動態(tài)存儲器分配 1 動態(tài)存儲器分配 一個動態(tài)存儲器分配器維護者一個進程的虛擬存儲器區(qū)域,稱為堆(heap)。在大多數的Unix系統(tǒng)中,堆是一個請求二進制零的區(qū)域,它緊接在未初始化的bss區(qū)域后開始,并向上生長(向更高的地址)。對于每個進程,內核維護者一個變量brk(讀作“break”),它指向棧的頂部。 分配器將堆視為一組不同大小的塊(block)的集合來維護。每個塊就是一個連續(xù)的虛擬存儲器組塊(chunk),要么是已分配的,要么是空閑的。已分配塊顯式地保留為供應用使用。空閑塊保持空閑,知道它顯式地被應用所分配。一個已分配的塊保持已分配狀態(tài),直到它被釋放,這種釋放要么是應用顯式執(zhí)行的,要么是存儲器分配器自身隱式執(zhí)行的。 2 分配器有兩種基本風格 顯式分配器:要求應用顯式地釋放任何已分配的塊。例如,C標準庫提供一種叫做malloc程序包的顯式分配器。C程序通過調用malloc分配一個塊,并通過調用free函數來釋放一個塊,C++中的new和delete操作符與C中的malloc和free相當。 隱式分配器:在另一個方面,要求分配器檢測何時一個已分配塊不再被程序使用,然后就釋放這個塊。隱式分配器也叫做垃圾收集器(garbage collector),而自動釋放未使用的已分配的塊的過程就做垃圾收集(garbage collection)。諸如,Lisp、ML以及Java之類的高級語言就依靠垃圾收集來釋放已分配的塊。 使用動態(tài)存儲器分配的重要原因是它們經常到程序實際運行時,才知道某些數據結構的大小。 造成對利用率很低的主要原因是一種稱為碎片(fragmentation)的現象,當雖然有未使用的存儲器但不能用來滿足分配請求是,就發(fā)生這種現象。包括:內部碎片(internal fragmentation)和外部碎片(external fragmentation)。 內部碎片的量化是簡單明了的,它就是已分配塊和它們的有效載荷之差的和。因此在任意時刻,內部碎片的數量只取決于請求的模式和分配器的實現方式。 外部碎片是當空閑存儲器合計起來足夠滿足一個分配請求,但是沒有一個單獨的空閑塊足夠大可以處理這個請求時發(fā)生的。因為外部碎片難以量化和不可能預測的,所以分配器典型地采用啟發(fā)式策略來試圖維持少量的大空閑塊,而不是維持大量的小空閑塊。 隱式空閑鏈表,空閑塊是通過頭部中的大小字段隱含地連接著的。分配器可以通過遍歷堆中所有的塊,從而間接地遍歷整個空閑塊的集合。 隱式空閑鏈表的優(yōu)點是簡單。顯著的缺點是任何操作的開銷,例如放置分配的塊,要求空閑鏈表的搜索與堆中已分配塊和空閑塊的總數呈線性關系。 很重要的一點就是意識到系統(tǒng)對齊要求和分配器對塊格式的選擇對分配器上的最小塊大小有強制的要求。沒有已分配塊或者空閑塊可以比這個最小值還小。 3 放置分配的塊(分配策略) 當一個應用請求一個k字節(jié)的塊時,分配器搜索空閑鏈表,查找一個足夠大、可以防止所請求塊的空閑塊。分配器執(zhí)行者中搜索的方式是由配置策略(placement policy)所確定的。一些常見的策略是首次適配(first fit)、下一次適配(next fit)和最佳適配(best fit)。 首次適配:從頭開始搜索空閑鏈表,選擇第一個合適的空閑塊。下一次適配和首次適配很相似,只不過不是從鏈表的起始處開始每次搜索,而是從上一次查詢結束的地方開始。最佳適配器檢查每個空閑塊,選擇匹配所需請求大小的最小空閑塊。 首次匹配的一個優(yōu)點是它趨于將大的空閑塊保留在表的后面。缺點是它區(qū)域在靠近鏈表起始處留下空閑塊的“碎片”,這就增加了對較大塊的搜索時間。最佳適配比首次適配和下一次適配的利用率要高一些。然而在簡單空閑鏈表組織結構中,比如隱式空閑鏈表中,使用最佳匹配的缺點是它對堆進行徹底的搜索。在后面會有更加精細負載的分離式空閑鏈表組織,它實現了最佳適配策略,而不需要進行徹底的堆搜索。 4 合并空閑塊 假碎片(fault fragmentation):當分配器釋放一個分配塊時,可能有其它空閑塊與這個新釋放的空閑塊相鄰。這些鄰接的空閑塊可能引起一種現象,叫做假碎片,這里有許多可用的空閑快被分割成為小的,無法使用的空閑塊。 立即合并(immediate coalescing):每次一個塊被釋放,就合并所有相鄰塊。這種方式有可能會產生一種形式的抖動,塊會反復地合并,然后馬上分割。反復地分配和釋放一個塊將產生大量不必要的分割和合并。所以快速的分配器通常會選擇某種形式的推遲合并。 延遲合并(deferred coalescing):等到某個稍晚的時候再合并。如,可以在直到某個請求失敗后,然后掃描整個堆,合并所有的空閑塊。 5 隱式空閑鏈表 給定一個到頭部的隱式空閑鏈表,唯一的選擇將是搜索整個鏈表,記住前面的位置,直到我們達到當前塊。使用隱式空閑鏈表,這意味著每次調用free的時間都與堆的大小成線性關系。即使使用更復雜精細的空閑鏈表組織,搜索時間也不會是常數。 Knuth提出了一種聰明而通用的技術,叫做邊界標記(boundary tag),允許在常數時間內進行對前面塊的合并。這種思想,是在每個塊的結尾處添加一個腳部(footer邊界標記),其中部步就是頭部的一個副本。如果每個塊包括這樣一個腳部,那么分配器就可以通過檢查前面一個塊的腳部,判斷前面一個塊的起始位置和狀態(tài),需要注意的是,前面一個塊的腳部總是位于當前塊起始位置的前一個字的距離處。 邊界標記的概念是簡單優(yōu)雅的,它對許多不同類型的分配器和空閑鏈表組織都是通用的。然而,它也存在一個潛在的缺陷,要求每個塊都保持一個頭部和一個腳部,在應用程序操作許多個小塊時,會產生顯著的存儲器開銷。幸運的是,有一種非常聰明的邊界標記的優(yōu)化方法,能夠使得在已分配塊中不再需要腳部?;叵胍幌?,當我們試圖在存儲器中合并當前塊以及前面的塊和后面的塊時,只有在前面的塊時空閑時,才會需要用到它的腳部。如果我們把前面塊的已分配/空閑位存放在當前塊中多出來的低位中,那么已分配的塊就不需要腳部了,這樣我們就可以將這個多出來的空間用作有效載荷了。 6 顯式空閑鏈表 因為塊分配與堆塊的總數呈線性關系,所以對于通用的分配器,隱式空閑鏈表是不適合的(盡管對于堆塊數量預先知道是很小的特殊的分配器來說,它是比較好的). 一種更好的方法是將空閑塊組織為某種形式的數據結構。根據定義,程序是不需要一個空閑塊的主體,所以實現這個數據結構的指針可以村販子啊這些空閑塊的主題里面。例如,堆可以組織成一個雙向空閑鏈表,在每個空閑塊中,都包含一個pred(祖先)和succ(后繼)指針。 使用雙向鏈表而不是隱式空閑鏈表,使首次適配的分配時間從塊綜述的線性時間減少到了空閑塊數量的線性時間。不過,釋放一個塊的時間可以是線性的,也可能是個常數,這取決于我們在空閑鏈表中對塊排序所選擇的策略。 一種方法是用后進先出(LIFO)的順序維護鏈表,將新釋放的塊放置在鏈表的開始處。使用LIFO的順序和首次適配的放置策略,分配器會最先檢查最近使用的塊。在這種情況下,釋放一個塊,可以在常數時間內完成。如果使用了邊界標記,那么合并也可以在常數時間內完成。 另一種方法是按照地址順序來維護鏈表,其中鏈表中每個塊的地址都小于它祖先的地址。在這種情況下,釋放一個塊需要線性時間的搜索,來定位合適的祖先。平衡點在于,按照地址排序的首次適配比LIFO排序的首次適配有更高的存儲器利用率,接近最佳適配的利用率。 一般而言,顯式鏈表的缺點是空閑塊必須足夠大,以包含所需要的指針,以及頭部和可能的腳部,這就導致了更大的最小塊大小,也潛在地提高了內部碎片的程度。 7 分離的空閑鏈表 一個單項的空閑鏈表的分配器需要與空閑塊數量成線性關系的時間來分配塊。一種流行的減少分配時間的方法,通常稱為分離存儲(segregated storage),維護多個空閑鏈表,其中每個鏈表中的塊有大致相等的大小。 主要有兩種:簡單分離存儲(simple segregated storage)和分離適配(segregated fit) 簡單分離存儲(simple segregated storage):使用簡單分離存儲,每個大小類的空閑鏈表包含大小相等的塊,每個塊的大小就是這個大小類中最大元素的大小。其優(yōu)點是分配和釋放都很簡單,缺點是容易造成內部和外部碎片。因為空閑塊是不會被分割的,所以可能會造成內部碎片。更糟的是,某些引用模式會引起極多的外部碎片,因為是不會合并空閑塊的。 分離適配(segregated fit):分配器維護一個空閑鏈表的數組。每個空閑鏈表是和一個大小類相關聯(lián)的,并且被組織成某種類型的顯式或隱式鏈表。每個鏈表包含潛在的大小不同的塊,這些快的大小是大小類的成員。下面一種簡單的版本是:為了分配一個塊,我們必須確定請求類的大小,并且對適當的空閑鏈表做首次適配,查找合適的塊。如果找到一個,我們(可選地)分割它,并將剩余的部分插入到適當的空閑鏈表中。如果找不到,我們就搜索下一個更大的大小類的空閑鏈表。如此重復,直到找到一個合適的塊。如果沒有空閑鏈表中有合適的塊,那么就向操作系統(tǒng)請求額外的對存儲器,從這個新的對存儲器中分配出一個塊,將剩余的部分放置在最大的大小類中。要釋放一個塊,我們執(zhí)行合并,并將結果方知道相應的空閑鏈表中。這種方法既快速,對存儲器的使用也很有效率。搜索時間減少了,因為搜索被限制在堆的某個部分,而不是整個堆。存儲器利用了得到了改善,因為有一個有趣的事實:對分離空閑鏈表的簡單的首次適配搜索相當于整個堆的最佳適配搜索。 8?伙伴系統(tǒng) 伙伴系統(tǒng)(buddy system)是分離適配的一種特例,其中每個大小類都是2的冪?;镜乃览锸羌僭O一個對的大小是2^m個字。我們?yōu)槊總€塊大小2^k維護一個分離空閑鏈表,其中 ? ? ? ? ?0=<k<=m。請求塊大小向上舍入到最接近2的冪。最開始時,只有一個大小為2^m個字的空閑塊。 伙伴系統(tǒng)分配器的主要優(yōu)點是它的快速搜索和快速合并。主要缺點是要求塊的大小為2的冪可能導致顯著的內部碎片。因此伙伴系統(tǒng)分配器不適合通用目的的工作服在。然而,對于某些與應用相關的工作負載,其中塊大小預先知道是2的冪,伙伴系統(tǒng)分配器就很有吸引力了。 10.7 垃圾收集 Mark&Sweep垃圾收集器由標記(mark)階段和清除(sweep)階段組成。標記階段標記處根節(jié)點的所有可達的和已分配的后繼,而后面的清除階段釋放每個未被標記的已分配塊。 想了解更多,請看后面的參考書籍。 10.8 C語言中常見的與存儲器有關的錯誤 1 間接引用壞指針 在晉城的虛擬地址空間中有較大的洞,沒有映射到任何有意義的數據。如果我們試圖間接引用一個指向這些洞的指針,那么操作系統(tǒng)就會以段異常終止這個程序。而且,虛擬存儲的某些區(qū)域是只讀的。試圖寫這些區(qū)域將造成以保護異常終止這個程序。 間接引用壞指針的一個常見示例的經典是scanf錯誤。做正確的事情的方法是傳遞給scanf一個格式串和變量的地址: scanf(“%d”,&val) 而C程序員初學者,則很容易傳遞val的內容,如 scanf(“%d”,val) 在這種情況下,scanf將把val的內容解釋為一個地址,并試圖講一個字寫到這個位置。在最好的情況下,程序立即以異常終止。最為糟糕的情況下,val的內容對應于虛擬存儲器的某個合法的讀/寫區(qū)域,于是我們就覆蓋了存儲器,這通常會造成災難性的、令人困惑的后果。 2 讀未初始化的存儲器 雖然.bbs存儲器位置(諸如未初始化的全局C變量)總是被加載器初始化為零,但是對于對存儲器卻并不是這樣的。 3 允許棧緩沖區(qū)溢出 如果一個程序不檢查輸入串的大小就寫入棧中的目標緩沖區(qū),那么這個程序就會有緩沖區(qū)溢出錯誤(buffer overflow bug)。 4 假設指針和他們指向的對象是相同大小的 5 造成錯位錯誤 錯位(off-by-one)錯誤是另一種常見的覆蓋性錯誤發(fā)生的原因: 6 引用指針,而不是它所指向的對象 如果我們不太注意C操作符的優(yōu)先級和結合性,我們就會錯誤地操作指針,而不是期望操作指針所指向的對象。 7 誤解指針運算 忘記了指針的算術操作是以他們指向的對象的大小為單位來進行的。 8 引用不存在的變量 不理解棧的規(guī)則,有時會引用不在合法的本地變量。 9 引用空閑堆塊中的數據 一個相似的錯誤是引用已經被釋放了的堆塊中的數據。 10 引起存儲器泄露 10.9 虛擬存儲器的幾個關鍵概念 一個關鍵的經驗教訓是,即使虛擬存儲器是由系統(tǒng)自動提供,它也是一種有限的存儲器資源,應用程序必須精明地管理它。正如我們從對動態(tài)存儲分配器的研究種學到的那樣,管理虛擬存儲器資源可能包括一些微妙的時間和空間的平衡。另一個關鍵的經驗教訓是,在C程序中很容易犯與存儲器有關的錯誤。壞的指針值,釋放已經空閑了的塊、不恰當的強制類型轉換和只恨運算,以及覆蓋堆結構,這些只是可能給我們帶來麻煩的許多方式中的一小部分。實際上,與存儲器有關的錯誤很討厭,這是導致Java產生的一個重要原因,Java取消了取變量地址的能力,完全控制了動態(tài)存儲分配器,從而嚴格控制了對虛擬存儲器的訪問。 10.10 小結 虛擬存儲器是對主存的一個抽象。支持虛擬存儲器的處理器通過使用一種叫做虛擬殉職的間接形式來引用主存。處理器產生一個虛擬地址,在被發(fā)送到主存之前,這個地址被翻譯成一個物理地址。從虛擬地址空間到物理地址空間的地址翻譯要求硬件和軟件緊密合作。專門的硬件通過使用頁表來翻譯虛擬地址,而頁表的內容是由操作系統(tǒng)提供的。 虛擬存儲器提供三個重要的功能:第一,它在主存中自動緩存最近使用的存放磁盤上的虛擬地址空間的內容。虛擬存儲器緩存中的塊叫做頁。對磁盤上頁的引用會觸發(fā)缺頁,缺頁將控制轉移到操作系統(tǒng)中的一個缺頁處理程序。缺頁處理程序將頁面從磁盤拷貝到主存緩存,如果必要,將寫回被驅逐的頁。第二,虛擬存儲器簡化了存儲器管理,進而又簡化了鏈接、在進程間共享數據、進程的存儲器分配,以及程序加載。最后虛擬存儲器通過在每條頁表條目中加入保護位,從而簡化了存儲器保護。 地址翻譯的過程將虛擬存儲器組塊(chunk)和磁盤上的文件塊關聯(lián)起來,來初始化虛擬存儲器組塊,這個郭晨剛成為存儲器映射。存儲器映射為共享數據、創(chuàng)建新的進程以及加載程序,提供了一種高效的機制。應用可以使用mmap函數來手工的創(chuàng)建和刪除虛擬地址空間的區(qū)域,然而,大多數程序依賴于動態(tài)存儲分配器,例如malloc,它管理虛擬地址空間區(qū)域內一個稱為堆的區(qū)域。動態(tài)存儲器分配器是一個有系統(tǒng)級感覺的應用程序,它直接操作存儲器,而無需類型系統(tǒng)的很多幫助。分配器有兩種類型:顯式分配器要求應用顯式地釋放它們的存儲器塊;隱式分配器(垃圾收集器)自動釋放任何無用的和不可達的塊。 對于C程序員來說,管理和使用虛擬地址儲存器是一件困難和容易出錯的任務。常見的錯誤示例包括:間接引用壞指針、讀取未初始化的存儲器,允許棧緩沖區(qū)溢出,假設指針和它們指向的對象大小相同,引用指針而不是它所指向的對象,誤解指針運算,引用不存在的變量,以及引起存儲器泄露等問題。[1]
PS:對于10.8部分,C語言中常見的錯誤這一方面還需要看更加專業(yè)的書,本參考是也只是泛泛而談,還需要結合其它書籍來參考,如《C和指針》[2]《C陷阱與缺陷》[3]。如后面參考文獻所示。 參考文獻 布賴恩特, O'Hallaron D, et al. 深入理解計算機系統(tǒng)[M]. 中國電力出版社, 2004. Bryant R, David Richard O H, David Richard O H. Computer systems: a programmer's perspective[M]. Upper Saddle River: Prentice Hall, 2003. Reek K A. Pointers on C[M]. Addison-Wesley Longman Publishing Co., Inc., 1997. Koenig A. C traps and pitfalls[M]. Pearson Education India, 1988.

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉