内核中与驱动相关的内存操作之五(kmalloc)

    在内核空间里面获取一段内存区域,最常用到的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;
    ... ...;
}

你可能感兴趣的:(Ldd)