1.相關指令linux
make oldconfig 配置內核shell
make 編譯內核app
make modules_instal 編譯安裝內核模塊函數
make install 引導新編譯的內核學習
uname –a 查看內核版本測試
lsmod 查看加載的模塊ui
insmod 加載模塊spa
rmmod 卸載模塊指針
dmesg 顯示開機信息blog
文件Makefile
obj-m :=syscall.o PWD := $(shell pwd) KDIR:=/lib/modules/4.4.0-21-generic/build all: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean
uname -r 顯示當前使用的內核信息,肯定本身當前linux的內核版本是多少
#include <stdio.h> #include <stdlib.h> int main() { unsigned long x = 0; x = syscall(223); //測試223號系統調用 printf("Hello, %ld\n", x); return 0; }
make -C $(LINUX_KERNEL_PATH) 指明跳轉到內核源碼目錄下讀取那裏的Makefile
M=$(CURRENT_PATH) 代表返回到當前目錄繼續執行當前的Makefile。
頭文件module.h,必須包含此文件;
頭文件kernel.h,包含經常使用的內核函數;
頭文件init.h包含宏_init和_exit,容許釋放內核佔用的內存。
對於頁的保護一般設置一個存取控制字段。當這個字段佔一位時,用於規定該頁中的內 容容許寫仍是讀;若是存取控制字段佔兩位,那麼它能夠表示存取控制爲讀寫、只讀和 只運行三種。當進程寫一個只讀頁時,系統就會經過中斷來報錯。
模塊參數以module_param(name,type,perm)的形式定義,其中name爲參數名,type爲參數的數據類型,perm是一個權限值,控制誰能夠存取模塊參數在sysfs中的表示。
頁全局目錄(Page Global Directory)
• 頁上級目錄(Page Upper Directory)
• 頁中間目錄(Page Middle Directory)
• 頁表(Page Table)
頁全局目錄包含若干頁上級目錄的地址,頁上級目錄又依次包含若干頁中間目錄的地址,而頁中間目錄又包含若干頁表的地址。每個頁表項指向一個頁框。線性地址所以被分紅五個部分。圖中沒有顯示位數,由於每一部分的大小與具體的計算機體系結構有關。
#include <linux/module.h> #include <asm/pgtable.h> #include <linux/version.h> #include <asm/page.h> #include <linux/gfp.h> #include <linux/page-flags.h> #include <linux/sched.h>//find_task_by_vpid #include <linux/mm.h>//find_vma MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("CONVERT USER VIRTUAL ADDRESS TO PHYADDRESS"); static int pid; static unsigned long va; module_param(pid,int,0644); module_param(va,ulong,0644); static int find_pgd_init(void) { unsigned long pa=0; struct task_struct *pcb_tmp=NULL; pgd_t *pgd_tmp=NULL; pud_t *pud_tmp=NULL; pmd_t *pmd_tmp=NULL; pte_t *pte_tmp=NULL; printk(KERN_ALERT "test:va=0x%lx,pid=%d.\n",va,pid); rcu_read_lock(); if( !( pcb_tmp = pid_task(find_vpid(pid), PIDTYPE_PID) ) ) { rcu_read_unlock(); printk(KERN_ALERT "Can't find the task %d.\n",pid); return 0; } rcu_read_unlock(); printk("The page index_table address = 0x%p\n\n",pcb_tmp->mm->pgd); printk(KERN_ALERT "pgd=0x%p\n",pcb_tmp->mm->pgd); if(!find_vma(pcb_tmp->mm,va)) { printk(KERN_ALERT "virt_addr 0x%lx not available.\n",va); return 0; } pgd_tmp=pgd_offset(pcb_tmp->mm,va); printk(KERN_ALERT "pgd_tmp=0x%p\n",pgd_tmp); printk(KERN_ALERT "pgd_val(*pgd_tmp)=0x%lx\n\n",pgd_val(*pgd_tmp)); if(pgd_none(*pgd_tmp)) { printk(KERN_ALERT "Not mapped in pgd.\n"); return 0; } pud_tmp=pud_offset(pgd_tmp,va); pmd_tmp=pmd_offset(pud_tmp,va); pte_tmp=pte_offset_kernel(pmd_tmp,va); if(pte_none(*pte_tmp)) { printk(KERN_ALERT "Not mapped in pte.\n"); return 0; } if(!pte_present(*pte_tmp)) { printk(KERN_ALERT "pte not in RAM,maybe swaped.\n"); return 0; } pa=(pte_val(*pte_tmp)&PAGE_MASK)|(va&~PAGE_MASK); printk(KERN_ALERT "Virtual address: 0x%lx in RAM is 0x%lx.\n",va,pa); printk(KERN_ALERT "Part content in 0x%lx is 0x%lx.\n",pa,*(unsigned long*)((char *)pa+PAGE_OFFSET)); int i; printk("some content:\n"); for(i=0;i<40;i=i+4) { printk("%lx\n",*(unsigned long*)((char*)pa+PAGE_OFFSET+i)); } return 0; } static void find_pgd_exit(void) { printk(KERN_ALERT "Goodbye.\n"); } module_init(find_pgd_init); module_exit(find_pgd_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("weiwei"); MODULE_DESCRIPTION("GET WESSAGE");
頁全局目錄包含若干頁上級目錄的地址,頁上級目錄又依次包含若干頁中間目錄的地址,而頁中間目錄又包含若干頁表的地址。每個頁表項指向一個頁框。線性地址所以被分紅五個部分。
函數名稱 |
說明 |
pte_user( ) |
讀 User/Supervisor 標誌。 |
pte_read( ) |
讀 User/Supervisor 標誌(表示 80x86 處理器上的頁不受讀的保護)。 |
pte_write( ) |
讀 Read/Write 標誌。 |
pte_exec( ) |
讀 User/Supervisor 標誌( 80x86 處理器上的頁不受代碼執行的保護)。 |
pte_dirty( ) |
讀 Dirty 標誌。 |
pte_young( ) |
讀 Accessed 標誌。 |
pte_file( ) |
讀 Dirty 標誌(當 Present 標誌被清除而 Dirty 標誌被設置時,頁屬於一個非線性磁盤文件映射)。 |
函數名稱 |
說明 |
mk_pte_huge( ) |
設置頁表項中的 Page Size 和 Present 標誌。 |
pte_wrprotect( ) |
清除 Read/Write 標誌。 |
pte_rdprotect( ) |
清除 User/Supervisor 標誌。 |
pte_exprotect( ) |
清除 User/Supervisor 標誌。 |
pte_mkwrite( ) |
設置 Read/Write 標誌。 |
pte_mkread( ) |
設置 User/Supervisor 標誌。 |
pte_mkexec( ) |
設置 User/Supervisor 標誌。 |
pte_mkclean( ) |
清除 Dirty 標誌。 |
pte_mkdirty( ) |
設置 Dirty 標誌。 |
pte_mkold( ) |
清除 Accessed 標誌(把此頁標記爲未訪問)。 |
pte_mkyoung( ) |
設置 Accessed 標誌(把此頁標記爲訪問過)。 |
pte_modify(p,v) |
把頁表項 p 的全部訪問權限設置爲指定的值 v 。 |
ptep_set_wrprotect() |
與 pte_wrprotect( ) 相似,但做用於指向頁表項的指針。 |
ptep_set_access_flags( ) |
若是 Dirty 標誌被設置爲 1 則將頁的訪問權設置爲指定的值,並調用flush_tlb_page() 函數。 |
ptep_mkdirty( ) |
與 pte_mkdirty( ) 相似,但做用於指向頁表項的指針。 |
ptep_test_and_clear_dirty( ) |
與 pte_mkclean( ) 相似,但做用於指向頁表項的指針並返回 Dirty 標誌的舊值。 |
ptep_test_and_clear_young( ) |
與 pte_mkold( ) 相似,但做用於指向頁表項的指針並返回 Accessed標誌的舊值。 |