在内核空间里面获取一段内存区域,最常用到的API就是kmalloc.
1.原型(lk2.6.22)如下:
static inline void *kmalloc(size_t size, gfp_t flags)
2.参数说明:
size:
要分配内存空间的大小,以字节为单位.
flags:
分配标志,用来控制kmalloc的行为.主要如下:
2-1.
GFP_KERNEL:
这是最常用的标志.以此标志控制的kmalloc行为的内存分配,会引起睡眠.因此,不能在进程上下文之外使用此标志来获取内存,否则会有很大的风险和隐患.如原子上下文、中断上下文、tasket、内核定时器这些场景,不应该使用此标志来获取内存;
GFP_ATOMIC:
针对上述GFP_KERNEL所带来的局限,GFP_ATOMIC分配内存期间不会引起睡眠.
__GFP_DMA:
在ZONE_DMA区间获取内存.例如X86,DMA区用在RAM的前16M,传统的ISA设备可以分配此DMA区域内存;
__GFP_HIGHMEM:
在ZONE_HIGHMEM区间获取内存.kmalloc是不能用来分配高端内存区间的内存的.
最常用的就是前面两个标志,后面的也往往接触到,其他的就比较"冷门".
3.返回值:
成功返回分配的目标内存空间的首地址;失败返回NULL.
4.应用场景:
4-1.kmalloc分配的内存绝大多数是位于ZONE_NORMAL的;
4-2.kmalloc分配的区域在物理内存中也是连续的;
4-3.它返回的是内核的逻辑地址.内核的逻辑地址是内核虚拟地址的子集,它与物理地址是线性关系,物理地址加上一个偏移量就是逻辑地址.比如CPU寄存器的值都被转换为逻辑地址以供内核访问的;
4-4.不能分配高端内存;
4-5.kmalloc分配的内存不应该大于128KB,如果只是分配几千个字节的内存,优先考虑非kmalloc之外的函数;
4-6.kmalloc分配的内存使用完之后,用kfree()释放掉.
5.实例:
kmalloc/kzmalloc在内核空间获取内存是最常见的,比比皆是.例如当一个USB插入到USB Port口的时候,因为是先有驱动后有设备,因此,会引发一个软件表征来表征此设备是一个"USB设备".因此,涉及到软件体的分配.如下:
static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange)
{
... ...;
udev = usb_alloc_dev(hdev, hdev->bus, port1);
... ...;
}
-->
struct usb_device *
usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
struct usb_device *dev;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
... ...;
}