malloc realloc kmalloc

本文介绍了Linux系统中kmalloc和kfree函数的应用,详细解释了kmalloc函数的参数及优先级设置。同时,文中还涵盖了中断号申请与释放的过程,并讨论了不同类型的内存地址在系统中的作用。
malloc是调用VirtualAlloc的。你可以直接调用VirtualAlloc,仅仅保留虚拟地址空间而不提交,这样的话,不会分配物理内存,仅仅保留一段虚拟地址空间不被映射而已。等到需要的时候再提交物理内存。 include/linux/kernel.h里声明了kmalloc()和kfree()。用于在内核模式下申 请和释放内存。 void *kmalloc(unsigned int len,int priority); void kfree(void *__ptr); 与 用户模式下的malloc()不同,kmalloc()申请空间有大小限制。长度是2的整次方。可以申请的最大长度也有限制。另外kmalloc()有 priority参数,通常使用时可以为GFP_KERNEL,如果在中断里调用用GFP_ATOMIC参数,因为使用GFP_KERNEL则调用者可能 进入sleep状态,在处理中断时是不允许的。 kfree()释放的内存必须是kmalloc()申请的。如果知道内存的大小,也可以用 kfree_s()释放。

在Linux中,驱动程序通常使用kmalloc函数申请内存,当然,也可以使用其它的函数申请。但因为kmalloc函数使用的比较多,我们重点说一下它。

void *kmalloc(size_t size, int flags)

kmalloc函数和malloc函数相似,它有两个参数,一个参数是size,即申请内存块的大小,这个参数比较简单,就像malloc中的参数一样。第二个参数是一个标志,在里面可以指定优先权之类的信息。在Linux中,有以下的一些优先权:

GFP_KERNEL,它的意思是该内存分配是由运行在内核模式的进程调用的,即当内存低于min_free_pages的时候可以让该进程进入睡眠;

GFP_ATOMIC,原子性的内存分配允许在实际内存低于min_free_pages时继续分配内存给进程。

GFP_DMA:此标志位需要和GFP_KERNEL、GFP_ATOMIC等一起使用,用来申请用于直接内存访问的内存页。

pte_present(pte_t pte) 该宏返回 一个布尔值,该布尔值用来表明数据页当前是否在内存中。在访问 pte 低位(这些位被 pte_page 丢弃)的几个函数当中,这是最常用的函数。当然这些页也许并不存在,如果内核已经把它们交换到磁盘,或者它们根本没有被装载的话。然而,页表本身总是出现 在当前的Linux实现中。把页表保存在内存中简化了内核代码,因为 pgd_offset 和其它相关项从来都不会失效。另一方面,一个"驻留存储大小"为零的进程也会在RAM中保存它的页表,这样,虽然浪费了一些内存,但总比用在其它方面要好 些。

中断号的申请

中断是非常宝贵的系统资源,在Linux中,系统维护着一个象输入输出设备注册表一样的中断资源注册表。任何驱动程序在使用一个中断,即作为中断处 理程序之前,要申请一个中断通道,并且,在处理完成之后,可以释放它。在Linux中,对于i386平台,这些函数定义在arch/i386 /kernel/irq.c中,申请和释放一个中断通道的函数是:

int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),      unsigned long irqflags,      const char * devname,      void *dev_id) void free_irq(unsigned int irq, void *dev_id)

其中各个参数的含义如下:

irq: 要申请的中断资源的中断号。 handler: 指向要安装的中断处理函数的指针。 irqflags: 这是一个与中断管理有关的各种选项的字节掩码。此项可选值如下:SA_INTERRUPT、SA_SHIRQ、SA_SAMPLE_RANDOM。如果不 置SA_INTERRUPT,则标明这个中断处理程序时一个"慢速"的中断处理程序,如果置了这一位,这个处理程序就是一个"快速"的中断处理程序。 devname:传递给request_irq的字符串,可以通过Linux的proc文件系统显示中断地拥有者的名字。 dev_id:这个参数用于共享中断号,驱动程序可以自由的任意的使用dev_id,除非强制使用中断共享,dev_id通常被置为NULL。

3、系统内存地址知识:

用户虚拟地址 该地址是用户空间的程序所能看到的常规地址。根据低层硬件体系结构的不同,用户地址可以是 32 位或者 64 位长,并且每个进程拥有自己独立的虚拟地址空间。 物理地址 该地址在处理器和系统内存之间使用。物理地址也是 32 或者 64 位长,在某些情况下,32 位系统也可以使用 64 位的物理地址。 总线地址 该地址在外设总线和内存之间使用。通常情况下,该地址和处理器所使用的物理地址是一样的,但并不总是这样。显然,总线地址非常依赖于体系结构。 内核逻辑地址 内 核逻辑地址组成了常规的内核地址空间,这些地址映射了大部分乃至所有的主内存,并被视为物理内存使用。在大多数的体系结构中,逻辑地址及其所关联的物理地 址之间的区别,仅仅在于一个常数的偏移量。逻辑地址使用硬件特有的指针大小,所以,在配置有大量内存的 32 位系统上,仅通过逻辑地址可能无法寻址所有的物理内存。在内核中,逻辑地址通常保存在 unsigned long 或者 void * 这样的变量中。由 kmalloc 返回的内存就是逻辑地址。 内核虚拟地址 这种地址和逻辑地址之间的区别在于,前者不一定 能够直接映射到物理地址。所有的逻辑地址可看成是内核虚拟地址;由函数 vmalloc 分配的内存具有虚拟地址,这种地址却不一定能直接映射到物理内存。本章后面要讲到的 kmap 函数也返回虚拟地址。虚拟地址通常保存在指针变量中。 如果我们拥有一个逻辑地址,可通过定义在 中的宏 _ _pa() 返回与其关联的物理地址。我们也可以使用 _ _va() 宏将物理地址映射回逻辑地址,但只能用于低端内存页。

低端内存 代表存在于内核空间的逻辑地址的内存。几乎在每种系统上读者都可能遇到,所有的内存都是低端内存。 高端内存 那些不存在逻辑地址的内存,因为相对于能够用 32 位来寻址的内存,系统通常有更多的物理内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值