Linux驅動的地址空間和硬體地址空間說明

來源:互聯網
上載者:User

 

作者:李強,華清遠見嵌入式學院講師。

有這麼幾個問題,在上驅動課程的時候,我感覺一直困擾著同學們:

●    使用者程式編譯串連形成的地址空間在什麼範圍內?
        ●    核心編譯後地址空間在什麼範圍內?
        ●    要對外設進行訪問,I/O的地址空間又是什麼樣的?

於是就有了這篇文章,從大概上把記憶體相關知識點介紹一下,減少同學們在驅動課時對記憶體的困惑

先回答第一個問題。Linux最常見的可執行檔格式為elf(Executable and Linkable Format)。在elf格式的可執行代碼中,ld總是從0x8000000開始安排程式的“程式碼片段”,對每個程式都是這樣。至於程式執行時在實體記憶體中的實際地址,則由核心為其建立記憶體映射時臨時分配,具體地址取決於當時所分配的實體記憶體頁面。

我們可以用Linux的公用程式obj對你的程式進行反組譯碼,從而知曉其位址範圍。

例如:假定我們有一個簡單的C程式Hello.c

# include <stdio.h>
        greeting ( )
        {
                printf(“Hello,world!\n”);
        }
        main()
        {
                greeting();
        }

之所以把這樣簡單的程式寫成兩個函數,是為了說明指令的轉移過程。我們用gcc和ld對其進行編譯和串連,得到可執行代碼hello。然後,用Linux的公用程式obj對其進行反組譯碼:
        $obj –d hello

得到的主要片段為:

08048568 <greeting>:
                8048568:        pushl     %ebp
                8048569:        movl     %esp, %ebp
                804856b:        pushl    $0x809404
                8048570:        call        8048474 <_init+0x84>
                8048575:        addl        $0x4, %esp
                8048578:        leave
                8048579:        ret
                804857a:        movl       %esi, %esi
                0804857c <main>:
                804857c:        pushl    %ebp
                804857d:        movl    %esp, %ebp
                804857f:         call        8048568 <greeting>
                8048584:        leave
                8048585:        ret
                8048586:        nop
                8048587:        nop

其中,像08048568這樣的地址,就是我們常說的虛地址(這個地址實實在在的存在,只不過因為物理地址的存在,顯得它是“虛”的罷了)。

虛擬記憶體、核心空間和使用者空間(部分內容參考《ULK》V3中文版)

Linux虛擬記憶體的大小為2^32(在32位的x86機器上),核心將這4G位元組的空間分為兩部分。最高的1G位元組(從虛地址0xC0000000到0xFFFFFFFF)供核心使用,稱為“核心空間”。而較低的3G位元組(從虛地址0x00000000 到0xBFFFFFFF),供各個進程使用,稱為“使用者空間”。因為每個進程可以通過系統調用進入核心,因此,Linux核心空間由系統內的所有進程共用。於是,從具體進程的角度來看,每個進程可以擁有4G位元組的虛擬位址空間(也叫虛擬記憶體)。

每個進程有各自的私人使用者空間(0~3G),這個空間對系統中的其他進程是不可見的。最高的1GB核心空間則為所有進程以及核心所共用。另外,進程的“使用者空間”也叫“地址空間”,在後面的敘述中,我們對這兩個術語不再區分。

使用者空間不是進程共用的,而是進程隔離的。每個進程最大都可以有3GB的使用者空間。一個進程對其中一個地址的訪問,與其它進程對於同一地址的訪問絕不衝突。比如,一個進程從其使用者空間的地址0x1234ABCD處可以讀出整數8,而另外一個進程從其使用者空間的地址0x1234ABCD處可以讀出整數20,這取決於進程自身的邏輯。

任意一個時刻,在一個CPU上只有一個進程在運行。所以對於此CPU來講,在這一時刻,整個系統只存在一個4GB的虛擬位址空間,這個虛擬位址空間是面向此進程的。當進程發生切換的時候,虛擬位址空間也隨著切換。由此可以看出,每個進程都有自己的虛擬位址空間,只有此進程啟動並執行時候,其虛擬位址空間才被運行它的CPU所知。在其它時刻,其虛擬位址空間對於CPU來說,是不可知的。所以儘管每個進程都可以有 4 GB的虛擬位址空間,但在CPU眼中,只有一個虛擬位址空間存在。虛擬位址空間的變化,隨著進程切換而變化。

從上面我們知道,一個程式編譯串連後形成的地址空間是一個虛擬位址空間,但是程式最終還是要運行在實體記憶體中。因此,應用程式所給出的任何虛地址最終必須被轉化為物理地址,所以,虛擬位址空間必須被映射到實體記憶體空間中,這個映射關係需要通過硬體體繫結構所規定的資料結構來建立。這就是我們所說的段描述符表和頁表,Linux主要通過頁表來進行映射。

於是,我們得出一個結論,如果給出的頁表不同,那麼CPU將某一虛擬位址空間中的地址轉化成的物理地址就會不同。所以我們為每一個進程都建立其頁表,將每個進程的虛擬位址空間根據自己的需要映射到物理地址空間上。既然某一時刻在某一CPU上只能有一個進程在運行,那麼當進程發生切換的時候,將頁表也更換為相應進程的頁表,這就可以實現每個進程都有自己的虛擬位址空間而互不影響。所以,在任意時刻,對於一個 CPU來說,只需要有當前進程的頁表,就可以實現其虛擬位址到物理地址的轉化。

核心空間到實體記憶體的映射

在驅動中我們提的比較多的就是核心空間與硬體記憶體位址,那麼我們下面來詳細介紹下核心空間和實際的硬體物理地址。

核心空間對所有的進程都是共用的,其中存放的是核心代碼和資料,而進程的使用者空間中存放的是使用者程式的代碼和資料,不管是核心程式還是使用者程式,它們被編譯和串連以後,所形成的指令和符號地址都是虛地址,而不是實體記憶體中的物理地址。

雖然核心空間佔據了每個虛擬空間中的最高1GB位元組,但映射到實體記憶體卻總是從最低地址(0x00000000)開始的,之所以這麼規定,是為了在核心空間與實體記憶體之間建立簡單的線性映射關係。其中,3GB(0xC0000000)就是物理地址與虛擬位址之間的位移量,在Linux代碼中就叫做PAGE_OFFSET。

我們來看一下在include/asm/i386/page.h標頭檔中對核心空間中地址映射的說明及定義:

#define __PAGE_OFFSET                (0xC0000000)
        ……
        #define PAGE_OFFSET                ((unsigned long)__PAGE_OFFSET)
        #define __pa(x)                ((unsigned long)(x)-PAGE_OFFSET)
        #define __va(x)                ((void *)((unsigned long)(x)+PAGE_OFFSET))

對於核心空間而言,給定一個虛地址x,其物理地址為“x- PAGE_OFFSET”,給定一個物理地址x,其虛地址為“x+ PAGE_OFFSET”。

這裡再次說明,宏__pa()僅僅把一個核心空間的虛地址映射到物理地址,而決不適用於使用者空間,使用者空間的地址映射要複雜得多,它通過分頁機制完成。

待續……

參考http://www.kerneltravel.net/chenlj/lecture7.pdf

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.