Linux内核API kmemdup

kmemdup函数功能描述:kmemdup( )函数的功能是根据给定的一段地址空间(这里由void * srcsize_t len决定),再分配一个内存空间(分配模式是gfp),并将原地址空间中的内容拷贝到新分配的内存空间中。

kmemdup文件包含

#include<linux/string.h>

kmemdup函数定义

在内核源码中的位置:linux-3.19.3/mm/util.c

函数定义格式:

void *kmemdup(const void *src, size_t len, gfp_t gfp)

kmemdup输入参数说明

  • src:给定的地址空间的起始地址。
  • len:要拷贝的原地址空间的长度。
  • gfp:分配模式,其取值及含义参考kmalloc( )函数的分析。

kmemdup返回参数说明

返回值为新分配的内存空间的起始地址,如果分配不成功则返回NULL。

kmemdup实例解析

编写测试文件:kmemdup.c

头文件及全局变量声明如下:

#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init kmemdup_init(void);
static void __exit kmemdup_exit(void);
struct page * pages = NULL;

模块初始化函数:

int __init kmemdup_init(void)
{
    pages = alloc_pages(GFP_KERNEL,0);  //分配一个物理页,pages为指向该页的指针
    if(! pages)
    {
        printk("alloc failed! \n");
        return -ENOMEM;
    }
    else
    {
        char * temp = (char *)pages;
        char x;
        *temp = 'a';
        int i = 0;
        for(; i <26; i ++)                  //为分配的页进行循环赋值
        {
            x = *temp;
            temp ++;
            *temp = x+1;
        }

        /*调用函数,拷贝pages为起始地址的26个字符,分配模式为GFP_KERNEL */
        char * addr = kmemdup( pages, 26, GFP_KERNEL);
        printk("addr = 0x%lx\n", (unsigned long)addr);        //输出所拷贝的目标起始地址
        printk("*addr = %c\n", *addr);                      //输出第一个字符
        printk("*addr+4 = %c\n", *(addr+4));                //输出第五个字符

        for(temp = addr; *temp ! ='\0'; temp ++)             //循环输出地址中的字符值
            printk("%c", *temp);
        printk("\n");
    }

    return 0;
}

模块退出函数:

void __exit kmemdup_exit(void)
{
    if(pages)
        __free_pages(pages,0);               //释放由alloc_pages( )所分配的页。
    printk("exit! \n");
}

模块初始化及退出函数调用:

module_init(kmemdup_init);
module_exit(kmemdup_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod kmemdup.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。

Linux内核API kmemdup

结果分析:

在本测试程序中,首先分配一个物理页作为原内存空间,然后将其26字节空间填充字符值,填充完后依次为abcd…xyz。之后我们调用kmemdup( )函数,参数值依次为pages、26、GFP_KERNEL,由字符型指针addr接收返回值。我们输出addr的值以及addr、addr+4的内容进行测试,由输出信息可知addr = 0xffff880145e831c0 ; *addr = a; *(addr + 4) = e;最后再输出新内存空间26字节的内容(这里通过循环实现),输出值为abcd…xyz,这说明原地址空间的内容被拷贝到了新分配的内存空间中。最后由__free_pages( )函数释放原内存空间pages。

赞(0)
未经允许不得转载:极客笔记 » Linux内核API kmemdup
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址