閱讀530 返回首頁    go 技術社區[雲棲]


linux驅動開發--內核空間中內存的申請與釋放

1、Linux內存管理

linux內存最小管理單位為頁(page),通常一頁為4kb。
linux係統中,在初始化時,內核為每個物理內存頁建立一個page的管理結構,操作物理內存時實際上就是操作page頁。

物理地址:出現在cpu地址總線上的尋址物理內存的地址信號,是地址變換的最終結果。
線性地址(虛擬地址):在32位cpu架構上,可以表示4G的地址空間,也就是0x00000000-0xFFFFFFFF。
邏輯地址:實際上是一個相對地址,是程序代碼經過編譯之後在匯編程序中出現的地址。


linux內核地址轉換:出現在機器語言指令(程序編譯後得到的二進製機器碼序列)中的內存地址都是邏輯地址,邏輯地址必須被轉換為線性地址,MMU將線性地址轉換成物理地址,最終實現對應物理內存的訪問。在linux係統中,邏輯地址和線性地址(虛擬地址)是一致的。

2、實例代碼

/**
*Copyright (c) 2013.TianYuan
*All rights reserved.
*
*文件名稱: kernelspace.c
*文件標識: 內核空間中內存的申請與釋放
*
*當前版本:1.0
*作者:wuyq 
*
*取代版本:xxx
*原作者:xxx
*完成日期:2013-11-18
*/
#include <linux/init.h>
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>

MODULE_LICENSE("GPL");
#define	PAGE_NUM	4/*編碼幻數*/

unsigned char *kernelkmalloc = NULL;
unsigned char *kernelpagemem = NULL;
unsigned char *kernelvmalloc = NULL;

static int __init kernelspace_init(void)
{
	int ret = -ENOMEM;
	/*
	*GFP_KERNEL:分配內存,分配過程中可能導致睡眠。
	*GFP_ATOMIC:分配過程中不會導致睡眠。
	*GFP_DMA:申請到的內存通常情況下,位於0~16M之間
	*__GFP_HIGNMEM:申請高端內存(物理地址896M以上的)
	*/
	kernelkmalloc = (unsigned char *)kmalloc(100, GFP_KERNEL);
	if(IS_ERR(kernelkmalloc)){
		printk("kmalloc failed!\n");
		ret = PTR_ERR(kernelkmalloc);
		goto failure_kmalloc;
	}
	printk("kmalloc space :0x%lx!\n",(unsigned long)kernelkmalloc);
	
	kernelpagemem = (unsigned char *)__get_free_pages(GFP_KERNEL, PAGE_NUM);/*請求或釋放的頁數的2的冪*/
	if(IS_ERR(kernelpagemem)){
		printk("get_free_pages failed!\n");
		ret = PTR_ERR(kernelpagemem);
		goto failure_get_free_pages;
	}
	printk("get_free_pages address:0x%lx\n",(unsigned long)kernelpagemem);
	
	kernelvmalloc = (unsigned char *)vmalloc(1024*1024);
	if(IS_ERR(kernelvmalloc)){
		printk("vmalloc failed!\n");
		ret = PTR_ERR(kernelvmalloc);
		goto failure_vmalloc;
	}
	printk("vmalloc address: 0x%lx\n",(unsigned long)kernelvmalloc);
	return 0;
failure_vmalloc:
	free_pages((unsigned long)kernelpagemem, PAGE_NUM);
failure_get_free_pages:
	kfree(kernelkmalloc);
failure_kmalloc:
	return ret;
}

static void __exit kernelspace_exit(void)
{
	vfree(kernelvmalloc);
	free_pages((unsigned long)kernelpagemem, PAGE_NUM);
	kfree(kernelkmalloc);
}

module_init(kernelspace_init);
module_exit(kernelspace_exit);

KERNELDIR ?=/root/Desktop/work/ldd3/linux-2.6.31_TX2440A
PWD := $(shell pwd)
obj-m += kernelspace.o

default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	@rm -f *.o *.ord* *.sy* *.mod.* *.ko



最後更新:2017-04-03 12:53:58

  上一篇:go C++編程規範之35:避免從並非要設計成基類的類中繼承
  下一篇:go 關於IP的一些問題