linux 訪問物理空間的方法



1. 通過軟件 hexedit

sudo hexedit /dev/mem

必須用管理員權限,這樣可以訪問到物理內存了,是不是很帥?


2. 程序編碼訪問物理地址


一、先補充一下基礎知識

1.打開設備文件:
    mem是一個字符設備文件,是計算機主存的一個映像。通常只有root用戶對其有讀寫權限。因此只有root用戶能進行這些操作。
    如果要打開設備文件/dev/mem,需要系統調用open()函數,作用是打開一個文件或設備,其函數原型爲:
    int open(const char *path, int flags);
    返回值:如果操作成功則返回一個文件描述符,否則返回-1
    形  參:
            path      被打開文件的路徑即文件名描述。
            flags     文件的訪問模式描述,可常用的選項見下:
                        O_RDONLY        只讀方式
                        O_WRONLY        只寫方式
                        O_RDWR          可讀寫方式
    說  明:此函數用於打開文件或者設備
    頭文件:#include <fcntl.h> #include <stat.h>  定義在/usr/include/fcntl.h中
2.讀取內存映像:
    內存映像其實在內存中創建一個與外存中文件完全相同的映像。用戶可以將整個文件映射到內存中,也可以將文件的一部分映射到內存中。
    使用操作內存的方法對文件進行操作。系統會將內存映像文件所做的改動反映到真實文件中去。
    在內存映像I/O的實現過程中需要用到一些系統調用:
    首先是創建內存映像文件的系統調用mmap()函數,其函數原型爲:
    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
    返回值:成功時,返回值爲指向內存映像起始地址的指針,當調用失敗時,返回值爲-1
    形  參:
            start      一個void指針,表示希望將文件映射到此指針指向的位置,通常爲NULL。
            length     定義內存映像文件所佔用的內存空間大小,以字節計。
            prot       內存映像文件的安全屬性,注意和open函數中的flags屬性保持一致。它的可使用的選項如下:
                          Flags                          含義
                        PROT_EXEC       被映像內存可能含義機器碼,可被執行
                        PROT_NONE       映像內存不允許訪問
                        PROT_READ       映像內存可讀
                        PROT_WRITE      映像內存可寫
            flags      內存映像的標誌,選項如下:
                          Flags                                   含義
                        MAP_FIXED       指定映射起始地址,如果由start和len指定的內存區重疊於現存的映射空間,重疊部分將會被丟棄。
                                        如果指定的起始地址不可用,操作將會失敗。並且起始地址必須落在頁的邊界上。
                        MAP_SHARED      與其它所有映射這個對象的進程共享映射空間。對共享區的寫入,相當於輸出到文件。
                                        直到msync()或者munmap()被調用,文件實際上不會被更新。 
                        MAP_PRIVATE     建立一個寫入時拷貝的私有映射。內存區域的寫入不會影響到原文件。
                                        這個標誌和以上標誌是互斥的,只能使用其中一個。 
                        MAP_NORESERVE   不要爲這個映射保留交換空間。當交換空間被保留,對映射區修改的可能會得到保證。
                                        當交換空間不被保留,同時內存不足,對映射區的修改會引起段違例信號。
                        MAP_LOCKED      鎖定映射區的頁面,從而防止頁面被交換出內存。 
                        MAP_GROWSDOWN   用於堆棧,告訴內核VM系統,映射區可以向下擴展。
                        MAP_ANONYMOUS   匿名映射,映射區不與任何文件關聯。
                        MAP_ANON        MAP_ANONYMOUS的別稱,不再被使用。 
                        MAP_FILE        兼容標誌,被忽略。 
                        MAP_32BIT       將映射區放在進程地址空間的低2GB,MAP_FIXED指定時會被忽略。
                                        當前這個標誌只在x86-64平臺上得到支持。
                        MAP_POPULATE    爲文件映射通過預讀的方式準備好頁表。隨後對映射區的訪問不會被頁違例阻塞。 
                        MAP_NONBLOCK    僅和MAP_POPULATE一起使用時纔有意義。不執行預讀,只爲已存在於內存中的頁面建立頁表入口。
            fd         要映射的文件的描述符。
            offset     所映射的數據內容 距離文件頭的偏移量。
    說  明:此函數用於將一個文件或它的一部分映射到內存中。
    頭文件:#include <sys/mman.h> #include <sys/types.h>  函數定義在/usr/include/sys/mman.h
3.撤銷內存映像的修改
    另外我們使用完內存映像文件後,要用系統調用函數munmap()函數來撤銷,其函數原型爲:
    int munmap(void *start, size_t length);
    返回值:成功時,返回值爲0;調用失敗時返回值爲 -1,並將errno設置爲相應值。
    形  參:
            start      要撤銷的內存映像文件的起始地址。
            length     要撤銷的內存映像文件的大小。
    說  明:當進程結束或利用exec相關函數來執行其他程序時,映射內存會自動解除,但關閉對應的文件描述詞時不會解除映射。
    頭文件:#include <sys/mman.h>
4.將內存映像的改動保存到外存中
    最後,如果我們要將內存映像的改動保存到外存中,還需要系統調用msync()函數,其函數原型爲:
    int msync(const void *start,size_t length,int flags);
    返回值:成功時,返回值爲0;調用失敗時返回值爲 -1,並將errno設置爲相應值。
    形  參:
            start      要保存到外存的那些源文件的起始地址。
            length     表示內存映像文件的大小。
            flags      設置了函數的相應操作,其具體選項如下:
                          Flags                      含義
                        MS_ASYNC           調用一個寫操作並返回
                        MS_INVALIDATE      映像到相同文件的內存映像數據更新
                        MS_SYNC            完成寫操作後函數返回
    說  明:進程在映射空間的對共享內容的改變並不直接寫回到磁盤文件中,往往在調用munmap()後才執行該操作。
            可以通過調用msync()函數來實現磁盤文件內容與共享內存區中的內容一致,即同步操作。
    頭文件:#include <sys/mman.h>
5.通過/dev/mem設備文件和mmap系統調用,可以將線性地址描述的物理內存映射到進程的地址空間,然後就可以直接訪問這段內存了。

接下來看一個小程序:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章