Linux内核API memdup_user

memdup_user函数功能描述:memdup_user( )函数的功能是根据给定的一段地址空间(这里由void __user *srcsize_t len决定),再分配一个内存空间,并将原地址空间中的内容拷贝到新分配的内存空间中,这里需要注意原地址空间是用户空间。

memdup_user文件包含

#include<linux/string.h>

memdup_user函数定义

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

函数定义格式:

void *memdup_user(const void __user * src, size_t len)

memdup_user输入参数说明

  • src:给定的地址空间的起始地址,它是一个用户空间的地址。
  • len:要拷贝的原地址空间的长度。

memdup_user返回参数说明

返回新分配的内存空间的起始地址。

memdup_user实例解析

编写测试文件:memdup_user.c

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

#include <linux/string.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
static int __init memdup_user_init(void);
static void __exit memdup_user_exit(void);
#define len 20

模块初始化函数:

int __init memdup_user_init(void)
{
    struct mm_struct * mm ;
    unsigned long mm_start ;
    mm = current->mm;                    //获取当前进程的地址空间
    mm_start = mm->mmap->vm_start;       //mm_start为当前进程地址空间的起始地址
    printk("mm_start = 0x%lx\n", mm_start);

    // 调用函数,从mm_start开始的地址空间拷贝len个字节的内容
    unsigned long * addr = (unsigned long *) memdup_user( mm_start, len);
    printk("addr = 0x%lx\n", (unsigned long)addr);       //输出所拷贝的目标起始地址
    printk("*addr = %lx\n", *addr);                    //输出第一个字
    printk("*addr+1 = %lx\n", *(addr+1));              //输出第四个字
    unsigned long * temp = addr;
    int i = 0;
    for(; i<len/4; i ++, temp ++)                        //循环输出地址中的字内容
        printk("%lx\n", *temp);
    return 0;
}

模块退出函数:

void __exit memdup_user_exit(void)
{
    printk("exit ok! \n");
}

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

module_init(memdup_user_init);
module_exit(memdup_user_exit);

实例运行结果及分析:

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

Linux内核API memdup_user

结果分析:

在本测试程序中,取当前进程的地址空间作为本测试函数所需要的用户空间,参数src的取值为当前进程地址空间的起始地址,len的值设置为20。为了防止以字节为单位读取的内存中的内容不可读,这里以字为单位读取。由输出结果可知,当前进程地址空间的起始地址为:mm_start = 0x7ff4dab26000;新分配的内存的起始地址为addr = 0xffff8800a165c520;新分配的内存空间第一个字的内容为*addr = 0x10102464c457f,第二个字的内容为*(addr+1) = 0x0。然后循环输出新内存空间中前len字节的内容(以字为单位输出),这些内容是由用户空间拷贝过去的,由输出结果可知它们依次为:0x10102464c457f,0x0, 0x7075646d003e0003,0x5d726573755f,0xffff8800a165cce0。

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

评论 抢沙发

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