導航:首頁 > 編程系統 > linux內核態地址空間

linux內核態地址空間

發布時間:2021-02-23 22:29:27

1. 如何查看linux的虛擬地址空間

一個進程的虛擬地址空間主要由兩個數據結來描述。一個是最高層次的:mm_struct,一個是較高層次的:vm_area_structs。最高層次的mm_struct結構描述了一個進程的整個虛擬地址空間。較高層次的結構vm_area_truct描述了虛擬地址空間的一個區間(簡稱虛擬區)。

1. MM_STRUCT結構

mm_strcut 用來描述一個進程的虛擬地址空間,在/include/linux/sched.h 中描述如下:

struct mm_struct {

struct vm_area_struct * mmap; /* 指向虛擬區間(VMA)鏈表 */

rb_root_t mm_rb; /*指向red_black樹*/

struct vm_area_struct * mmap_cache; /* 指向最近找到的虛擬區間*/

pgd_t * pgd; /*指向進程的頁目錄*/

atomic_t mm_users; /* 用戶空間中的有多少用戶*/

atomic_t mm_count; /* 對"struct mm_struct"有多少引用*/

int map_count; /* 虛擬區間的個數*/

struct rw_semaphore mmap_sem;

spinlock_t page_table_lock; /* 保護任務頁表和 mm->rss */

struct list_head mmlist; /*所有活動(active)mm的鏈表 */

unsigned long start_code, end_code, start_data, end_data;

unsigned long start_brk, brk, start_stack;

unsigned long arg_start, arg_end, env_start, env_end;

unsigned long rss, total_vm, locked_vm;

unsigned long def_flags;

unsigned long cpu_vm_mask;

unsigned long swap_address;

unsigned mpable:1;

/* Architecture-specific MM context */

mm_context_t context;

};

對該結構進一步說明如下:

在內核代碼中,指向這個數據結構的變數常常是mm。

每個進程只有一個mm_struct結構,在每個進程的task_struct結構中,有一個指向該進程的結構。可以說,mm_struct結構是對整個用戶空間的描述。

一個進程的虛擬空間中可能有多個虛擬區間(參見下面對vm_area_struct描述),對這些虛擬區間的組織方式有兩種,當虛擬區較少時採用單鏈表,由mmap指針指向這個鏈表,當虛擬區間多時採用「紅黑樹(red_black tree)」結構,由mm_rb指向這顆樹。在2.4.10以前的版本中,採用的是AVL樹,因為與AVL樹相比,對紅黑樹進行操作的效率更高。

因為程序中用到的地址常常具有局部性,因此,最近一次用到的虛擬區間很可能下一次還要用到,因此,把最近用到的虛擬區間結構應當放入高速緩存,這個虛擬區間就由mmap_cache指向。

指針pgt指向該進程的頁目錄(每個進程都有自己的頁目錄,注意同內核頁目錄的區別),當調度程序調度一個程序運行時,就將這個地址轉成物理地址,並寫入控制寄存器(CR3)。

由於進程的虛擬空間及其下屬的虛擬區間有可能在不同的上下文中受到訪問,而這些訪問又必須互斥,所以在該結構中設置了用於P、V操作的信號量mmap_sem。此外,page_table_lock也是為類似的目的而設置。

雖然每個進程只有一個虛擬地址空間,但這個地址空間可以被別的進程來共享,如,子進程共享父進程的地址空間(也即共享mm_struct結構)。所以,用mm_user和mm_count進行計數。類型atomic_t實際上就是整數,但對這種整數的操作必須是「原子」的。

另外,還描述了代碼段、數據段、堆棧段、參數段以及環境段的起始地址和結束地址。這里的段是對程序的邏輯劃分,與我們前面所描述的段機制是不同的。

mm_context_t是與平台相關的一個結構,對i386 幾乎用處不大。

在後面對代碼的分析中對有些域給予進一步說明。

2. VM_AREA_STRUCT 結構

vm_area_struct描述進程的一個虛擬地址區間,在/include/linux/mm.h中描述如下:

struct vm_area_struct

struct mm_struct * vm_mm; /* 虛擬區間所在的地址空間*/

unsigned long vm_start; /* 在vm_mm中的起始地址*/

unsigned long vm_end; /*在vm_mm中的結束地址 */

/* linked list of VM areas per task, sorted by address */

struct vm_area_struct *vm_next;

pgprot_t vm_page_prot; /* 對這個虛擬區間的存取許可權 */

unsigned long vm_flags; /* 虛擬區間的標志. */

rb_node_t vm_rb;

/*

* For areas with an address space and backing store,

* one of the address_space->i_mmap{,shared} lists,

* for shm areas, the list of attaches, otherwise unused.

*/

struct vm_area_struct *vm_next_share;

struct vm_area_struct **vm_pprev_share;

/*對這個區間進行操作的函數 */

struct vm_operations_struct * vm_ops;

/* Information about our backing store: */

unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE

units, *not* PAGE_CACHE_SIZE */

struct file * vm_file; /* File we map to (can be NULL). */

unsigned long vm_raend; /* XXX: put full readahead info here. */

void * vm_private_data; /* was vm_pte (shared mem) */

};

vm_flag是描述對虛擬區間的操作的標志,其定義和描述如下

標志名 描述

VM_DENYWRITE 在這個區間映射一個打開後不能用來寫的文件

VM_EXEC 頁可以被執行。

VM_EXECUTABLE 頁含有可執行代碼。

VM_GROWSDOWN 這個區間可以向低地址擴展。

VM_GROWSUP 這個區間可以向高地址擴展。

VM_IO 這個區間映射一個設備的I/O地址空間。

VM_LOCKED 頁被鎖住不能被交換出去。

VM_MAYEXEC VM_EXEC 標志可以被設置。

VM_MAYREAD VM_READ 標志可以被設置。

VM_MAYSHARE VM_SHARE 標志可以被設置。

VM_MAYWRITE VM_WRITE 標志可以被設置。

VM_READ 頁是可讀的。

VM_SHARED 頁可以被多個進程共享。

VM_SHM 頁用於IPC共享內存。
VM_WRITE 頁是可寫的。

較高層次的結構vm_area_structs是由雙向鏈表連接起來的,它們是按虛地址的降順序來排列的,每個這樣的結構都對應描述一個相鄰的地址空間范圍。之所以這樣分割,是因為每個虛擬區間可能來源不同,有的可能來自可執行映象,有的可能來自共享庫,而有的則可能是動態分配的內存區,所以對每一個由vm_area_structs結構所描述的區間的處理操作和它前後范圍的處理操作不同。因此Linux 把虛擬內存分割管理,並利用了虛擬內存處理常式(vm_ops)來抽象對不同來源虛擬內存的處理方法。不同的虛擬區間其處理操作可能不同,Linux在這里利用了面向對象的思想,即把一個虛擬區間看成一個對象,用vm_area_structs描述了這個對象的屬性,其中的vm_operation結構描述了在這個對象上的操作,其定義在/include/linux/mm.h中:

/*

* These are the virtual MM functions - opening of an area, closing and

* unmapping it (needed to keep files on disk up-to-date etc), pointer

* to the functions called when a no-page or a wp-page exception occurs.

*/

struct vm_operations_struct {

void (*open)(struct vm_area_struct * area);

void (*close)(struct vm_area_struct * area);

struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int unused);

};

vm_operations結構中包含的是函數指針;其中,open、close分別用於虛擬區間的打開、關閉,而nopage用於當虛存頁面不在物理內存而引起的「缺頁異常」時所應該調用的函數。

3.紅黑樹結構

Linux內核從2.4.10開始,對虛擬區的組織不再採用AVL樹,而是採用紅黑樹,這也是出於效率的考慮,雖然AVL樹和紅黑樹很類似,但在插入和刪除節點方面,採用紅黑樹的性能更好一些,下面對紅黑樹給予簡單介紹。
一顆紅黑樹是具有以下特點的二叉樹:
每個節點著有顏色,或者為紅,或者為黑
根節點為黑色
如果一個節點為紅色,那麼它的子節點必須為黑色
從一個節點到葉子節點上的所有路徑都包含有相同的黑色節點數

2. linux 中內核申請的動態空間在什麼地方

在堆中

3. 為什麼Linux內核要把內核地址放在高地址空間內

我們知道現在操作系統都是採用虛擬存儲器,那麼對32位操作系統而言,它的定址空間(虛擬存儲空間)為4G(2的32次方)。操心系統的核心是內核,獨立於普通的應用程序,可以訪問受保護的內存空間,也有訪問底層硬體設備的所有許可權。為了保證用戶進程不能直接操作內核,保證內核的安全,操心系統將虛擬空間劃分為兩部分,一部分為內核空間,一部分為用戶空間。針對linux操作系統而言,將最高的1G位元組(從虛擬地址0xC0000000到0xFFFFFFFF),供內核使用,稱為內核空間,而將較低的3G位元組(從虛擬地址0x00000000到0xBFFFFFFF),供各個進程使用,稱為用戶空間。每個進程可以通過系統調用進入內核,因此,Linux內核由系統內的所有進程共享。於是,從具體進程的角度來看,每個進程可以擁有4G位元組的虛擬空間
需要注意的細節問題:
(1) 內核空間中存放的是內核代碼和數據,而進程的用戶空間中存放的是用戶程序的代碼和數據。不管是內核空間還是用戶空間,它們都處於虛擬空間中。
(2) Linux使用兩級保護機制:0級供內核使用,3級供用戶程序使用。
內核態與用戶態:
(1)當一個任務(進程)執行系統調用而陷入內核代碼中執行時,稱進程處於內核運行態(內核態)。此時處理器處於特權級最高的(0級)內核代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。
(2)當進程在執行用戶自己的代碼時,則稱其處於用戶運行態(用戶態)。此時處理器在特權級最低的(3級)用戶代碼中運行。當正在執行用戶程序而突然被中斷程序中斷時,此時用戶程序也可以象徵性地稱為處於進程的內核態。因為中斷處理程序將使用當前進程的內核棧。

4. LINUX內核空間與用戶空間分別是什麼意思

關於內核空間和用戶空間,說的是linux驅動程序一般工作在內核空間,但也可以工作在用戶空間。下面將詳細解析,什麼是內核空間,什麼是用戶空間,以及如何判斷他們。
Linux簡化了分段機制,使得虛擬地址與線性地址總是一致,因此,Linux的虛擬地址空間也為0~4G.Linux內核將這4G位元組的空間分為兩部分。將最高的1G位元組(從虛擬地址0xC0000000到0xFFFFFFFF),供內核使用,稱為"內核空間".而將較低的3G位元組(從虛擬地址 0x00000000到0xBFFFFFFF),供各個進程使用,稱為"用戶空間)。因為每個進程可以通過系統調用進入內核,因此,Linux內核由系統內的所有進程共享。於是,從具體進程的角度來看,每個進程可以擁有4G位元組的虛擬空間。
Linux使用兩級保護機制:0級供內核使用,3級供用戶程序使用。每個進程有各自的私有用戶空間(0~3G),這個空間對系統中的其他進程是不可見的。最高的1GB位元組虛擬內核空間則為所有進程以及內核所共享。
內核空間中存放的是內核代碼和數據,而進程的用戶空間中存放的是用戶程序的代碼和數據。不管是內核空間還是用戶空間,它們都處於虛擬空間中。

5. linux內核調用哪些介面分配內核地址空間的內存

kmalloc/kfree

類似於來標准C中的malloc/free,kmalloc/kfree是內核源中的用於常規內存分配的介面。

例如,申請1024位元組的內核地址空間:

	char*buff;
buff=kmalloc(1024,GFP_KERNEL);
if(!buff)
return-ENOMEM;

還有什麼問題的話,可以私信我哦

6. 為什麼linux操作系統內核在虛擬地址空間的3GB處

1: 並不是所有平台都抄在3G
2:i386沒有PAE,並且編譯時沒有特別指定的時候才在3G
3:在這種情況下,由於地址匯流排最大隻能訪問4G的空間,並且為了在切換入內核空間時不需要重新載入內核的頁表,使用了一個技巧:讓內核與用戶空間影射到同一內存段。根據實際需要,給內核保留了1G的內存空間,並且為了讓應用程序看起來是從0地址開始的,那麼內核的1G內存段就佔用了3G~4G的空間。這就回答了你的問題。
4:其實這種方法不是唯一的,比如,可以讓內核少佔用一些空間,那麼就不是3G了。或者,讓內核與應用程序不映射到同一個內存空間,那麼用戶程序可以使用幾乎全部的4G空間(有些patch可以做到,但這樣的話內核<->用戶態切換時代價很大。說幾乎4G的原因是:調用syscall時還是需要一段內存傳遞參數的)。

7. linux0.11內核中每個進程的線性地址空間為什麼是64m

應該是每當新建一個進程後,在線性地址空間中代碼段和數據段的大小被設置成了64MB(嗯,記得是這樣,好久沒看了,記不太清)

8. Linux的內核空間和用戶空間是如何劃分的(以32位系統為例)

Linux將4G的地址劃分為用戶空間和內核空間兩部分。在Linux內核的低版本中(2.0.X),通常0-3G為用戶空間,3G-4G為內核空間。這個分界點是可以可以改動的。
正是這個分界點的存在,限制了Linux可用的最大內存為2G.而且要通過重編內核,調整這個分界點才能達到。實際上還可以有更好的方法來解決這個問題。由於內核空間與用戶空間互不重合,所以可以用段機制提供的保護功能來保護內核級代碼。
2.2.X版的內核對此進行了改動。這樣內核空間擴張到了4G。從表面上看內核的基地址變為了0,但實際上,內核通常仍在虛址3G以上。
用戶空間在2.2.X中從直觀上變為0-4G,讓人迷惑,不是可以直接訪問內核了?
其實不然,同過使用頁機制提供的保護,阻止了用戶程序訪問內核空間。

windows是使用的一個開關設置的,一般是1G,設置過開關之後,用花空間就可以達到3G

另外,附上一片文章吧,這個是64位系統上面的。。。希望能給你啟發~~~試著編譯下內核吧!
http://www.linuxidc.com/Linux/2011-03/33764.htm

閱讀全文

與linux內核態地址空間相關的資料

熱點內容
手機釘釘下載下來的文件在哪裡找 瀏覽:545
男主是女主的三叔 瀏覽:514
經濟師萬題庫大數據 瀏覽:996
獲取appsetting 瀏覽:920
蘋果7plus哪個顏色保值 瀏覽:869
蜜桃風月 瀏覽:533
1個電影多少流量 瀏覽:971
日本瑜伽電影 瀏覽:463
有一部電影講一個男的做鴨 瀏覽:247
看視頻的網址推薦 懂的 瀏覽:411
南昌大數據培訓 瀏覽:603
每天自動1的代碼 瀏覽:375
因為存在系統錯誤代碼193 瀏覽:56
ip網路適配器是什麼 瀏覽:61
印尼愛情電影 瀏覽:794
求一個網站帶小說的那種 瀏覽:56
pdf文件如何不能復制 瀏覽:612
都市連媽媽都收的小說 瀏覽:300
java第一步pdf 瀏覽:984
javahourofday 瀏覽:158

友情鏈接