成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊操作系統的內存管理

系統 其他OS
brk()的作用也只是通知Linux內核哪個范圍的堆內存是可用的,真正的物理內存頁是在進程實際讀寫內存的時候才會申請,而且是由內核根據寫時復制/需求加載自動完成的,應用程序感知不到這點。

?內存管理,是操作系統的主要功能。

操作系統從啟動一直到創建0號進程(idle進程),運行的大部分代碼都跟內存有關。

操作系統的內存管理,大概分這么幾個層次:

1.物理內存管理

物理內存是電腦上的真實內存大小,這個數據可以通過BIOS獲取。

在分頁之后,物理內存的管理結構是個數組,每項表示1個物理內存頁,每頁4096字節。

如下圖:

物理內存的管理結構

在一個簡單的內核demo里,物理內存頁的管理結構可以只有一項:

atomic_t refs;

即,物理內存頁的引用計數:計數為0表示空閑,> 0表示正在使用,具體數字表示共享這一頁的進程個數。

簡單的內核demo一般是不支持SMP架構的,所以自旋鎖(spinlock)也就省了。

在對稱多處理器(SMP)的CPU上,因為全局數據結構會被多個CPU并發訪問,所以要加自旋鎖。

那么,物理內存頁的管理結構至少有2項:

atomic_t spinlock;
atomic_t refs;

自旋鎖的作用,與應用程序里的鎖(mutex)差不多,只是它在獲取失敗之后會不斷地再次獲取,直到成功。

void spin_lock(atomic_t* lock)
{
while (spin_trylock(lock) == 0);
}

這就是給自旋鎖加鎖的函數,while循環直到成功,不成功時就自旋在那里一直轉圈,所以叫自旋鎖。

它在(對稱多處理器)SMP環境里用于保護共享的數據結構:當一個CPU持有自旋鎖時,另一個CPU沒法訪問共享數據。

如果是單個CPU的環境,沒必要用自旋鎖,直接關閉中斷就行了。

單個CPU的情況下,關了中斷就可以阻止內核的并發,共享數據也就不會被踩踏了。

但多個CPU必須使用自旋鎖,因為關中斷只能關閉當前CPU的,沒法關其他CPU的:這時需要自旋鎖保護共享數據。

物理內存的管理數組,是最重要的全局共享數據。

當需要給一個進程申請內存的時候,哪個內存頁是空閑的,哪個已經被使用了,全靠查看這個數組。

加自旋鎖的時候一定要先關中斷,因為如果在加了鎖之后、關中斷之前、正好有個中斷來了,而在中斷處理函數里再次請求加同一個鎖,那就會遞歸死鎖了。

Linux內核的關中斷加鎖的函數叫:spin_lock_irqsave().

Linux內核的分配物理內存頁的函數叫:get_free_pages(),它可以分配1頁或連續的多頁內存。

如果分配多頁內存的話,起始地址是要按頁數對齊的。

2.虛擬內存管理

虛擬內存都是通過進程的頁表管理的。

為了節省物理內存,新創建的進程是與父進程共享同一套物理內存頁的。

只有新進程要寫某個內存頁時,才會給它復制一份新的物理內存頁,然后取消該頁與父進程的共享,這就是寫時復制。

寫時復制的過程

寫時復制的過程:

1)申請一個新內存頁,

2)把老內存頁的內容,復制到新內存頁上,

3)把新內存頁的地址填入子進程的頁表,

4)把老內存頁的引用計數減1。

所以,新進程剛被創建出來時,它的用戶空間并沒有自己的物理內存頁,只有當運行需要時才一點點地通過寫時復制添加,以讓物理內存最大限度的空閑著。

另一個讓物理內存最大限度空閑著的機制,就是需求加載:

1)當mmap一個文件時,操作系統并不會直接為這個文件分配內存,并且把它的內容加載到內存里,

2)而是當進程真去讀這個文件的某一部分時,才給它申請物理內存頁,并且把這一部分內容從磁盤讀到內存。

copy on write,load on read.

不到火燒眉毛的時候,Linux系統是不會把物理內存給進程的?

3.用戶態的內存函數

以上的這些機制都是OS內核里的,應用程序的代碼不需要管這些。

應用程序分配內存的最底層函數,就是brk()系統調用。

brk()函數

brk()是一個系統調用,它的作用就是修改應用程序的數據段的結尾,從而分配或回收應用程序的堆空間。

brk系統調用的功能

C庫里的把它封裝成了sbrk()和brk()兩個函數,讓它使用起來更符合人們的習慣:

sbrk()用于申請內存:void* sbrk(int increment);

brk()用于回收內存:int brk(void* addr);

實際上,Linux系統只有1個brk()系統調用,它既設置進程數據段的末尾,又會把這個值返回給應用程序。

Linux內核頭文件的sys_brk()函數

Linux內核的頭文件里,brk()系統調用的處理函數sys_brk()是這么定義的,如上圖。

如果想直接使用系統調用,可以使用Linux的syscall()函數,依次傳入調用號和參數列表,就可以看到哪些是真實的系統調用,哪些是C庫的封裝。

syscall()函數的聲明是:long syscall(long number, ...);

它的參數是可變的,系統調用的參數最多只有6個,因為寄存器的個數有限。

在sbrk() 和 brk()的基礎上再封裝,就是人們經常使用的malloc() 和 free()了。

malloc() 申請的內存是一塊塊的,可以不按次序釋放,而不影響使用。

brk() 和 sbrk() 申請的內存必須按次序釋放,因為它會修改進程的數據段結尾:

數據段結尾(brk)之外的堆空間如果被使用,就屬于段錯誤。

所以,Linux man手冊里說明了,應用程序不要用sbrk()和brk()申請和釋放內存。

brk()的作用也只是通知Linux內核哪個范圍的堆內存是可用的,真正的物理內存頁是在進程實際讀寫內存的時候才會申請,而且是由內核根據寫時復制/需求加載自動完成的,應用程序感知不到這點。

Linux還會把不常用的物理內存頁交換到磁盤上(即swap分區),以騰出更多的內存。

所以,在內存不足時,磁盤的讀寫頻次也會升高。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2021-03-28 13:54:31

操作系統內存管理

2009-08-17 08:32:56

Linux操作系統內存管理Linux

2023-02-26 14:34:18

OSW操作系統監控

2021-06-11 07:26:16

操作系統內存管理Cpu

2025-01-13 00:30:17

2022-09-22 08:06:29

計算機平板微信

2017-05-16 14:31:09

2024-08-28 17:45:00

內存Linux

2021-08-16 06:56:21

Slice數組類型內存

2021-03-26 06:27:08

操作系統應用軟件瀏覽器

2021-01-07 07:53:10

JavaScript內存管理

2010-04-20 14:17:21

Unix操作系統

2010-04-07 15:37:16

Unix操作系統

2010-04-08 17:05:21

Unix操作系統

2010-04-14 13:59:45

Unix操作系統

2012-08-13 10:19:03

IBMdW

2022-11-02 07:23:06

2018-08-09 16:12:59

操作系統內存分配

2023-11-06 08:47:52

操作系統物理內存

2023-06-09 08:06:14

操作系統調度器LLM
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久午夜片 | 99re超碰| 精品久久一区二区 | 久草网在线视频 | 伊人狠狠干 | 91看片网址| 亚洲综合色视频在线观看 | 国产精品a一区二区三区网址 | 国产欧美在线观看 | 久久国产婷婷国产香蕉 | 日本天堂一区二区 | 伊人久久在线观看 | 亚洲精品一区中文字幕 | 精品一区二区视频 | 国产中文原创 | 欧美xxxⅹ性欧美大片 | 99久久久久久 | 在线午夜| 国产成人精品一区二 | 精品一区二区三区中文字幕 | 精品欧美一区二区三区精品久久 | 成人福利网 | 色香蕉在线 | 精品一区二区三区不卡 | 久久久久亚洲精品国产 | 国产精品黄色 | 欧美男人天堂 | 精品国产乱码久久久 | 在线观看黄色电影 | 亚洲一区免费在线 | 亚洲精品一区二区三区蜜桃久 | 波多野结衣二区 | 国产日韩在线观看一区 | 韩三级在线观看 | 亚洲精品欧美 | 欧美小视频在线观看 | 精品一区在线看 | 日韩中文字幕免费在线观看 | 91精品国产综合久久久密闭 | 欧美亚洲成人网 | 久久99精品久久久久久 |