jlkmaster 发表于 2012-01-31 23:15

Linux设备驱动详解globalmem驱动 求助

insmod时出现:globalmem :unknown symbol malloc_sizes
insmod:can't insert 'globalmem.ko' :unknown symbol in module or invalid parameter,到底应该如何解决呢?在此谢谢了。
我的内核版本是2.6.31.
查看内核源码知道mm中的slab.c中有malloc_sizes的定义及导出符号。
我的源文件如下:
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>


#define GLOBALMEM_SIZE 4096 /*全局内存大小:4KB*/
#define MEM_CLEAR 0x1       /*清零全局内存*/
#define GLOBALMEM_MAJOR 0 /*预设的globalmem的主设备号*/

static globalmem_major = GLOBALMEM_MAJOR;
/*globalmem设备结构体*/
struct globalmem_dev
{
        struct cdev cdev;    /*cdev结构体*/
        unsigned char mem; /*全局内存*/
};



struct globalmem_dev *globalmem_devp; /*设备结构体指针*/

/*文件打开函数*/
int globalmem_open(struct inode *inode, struct file *filp)
{
        /*将设备结构体指针赋值给文件私有数据指针*/
        filp->private_data = globalmem_devp;
        return 0;
}

/*文件释放函数*/
int globalmem_release(struct inode *inode, struct file *filp)
{
        return 0;
}

/*ioctl设备控制函数*/
static int globalmem_ioctl(struct inode *inode, struct file *filp,
                        unsigned int cmd, unsigned long arg)
{
        struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
        switch(cmd)
        {
                case MEM_CLEAR:
                        memset(dev->mem, 0, GLOBALMEM_SIZE);
                        printk(KERN_INFO "globalmem is set to zero\n");
                        break;
                default:
                        return -EINVAL;
        }
        return 0;
}

/*读函数*/
static ssize_t globalmem_read(struct file *filp, char __user *buf,
        size_t size, loff_t *ppos)
{
        unsigned long p = *ppos;
        unsigned int count =size;
        int ret = 0;
        struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
       
        /*分析和获取有效的写长度*/
        if(p >= GLOBALMEM_SIZE)
                return 0;
        if(count > GLOBALMEM_SIZE - p)
                count = GLOBALMEM_SIZE -p;
       
        /*读数据到用户空闲*/
        if(copy_to_user(buf, (void *)(dev->mem + p), count))
        {
                ret = -EFAULT;
        }
        else
        {
                *ppos += count;
                ret = count;
                printk(KERN_INFO "read %d bytes(s) from %d\n",count, p);
        }
       
        return ret;
}

/*写函数*/
static ssize_t globalmem_write(struct file *filp, const char __user *buf,
        size_t size, loff_t *ppos)
{
        unsigned long p = *ppos;
        unsigned int count =size;
        int ret = 0;
        struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
       
        /*分析和获取有效的写长度*/
        if(p > GLOBALMEM_SIZE)
                return 0;
        if(count > GLOBALMEM_SIZE - p)
                count = GLOBALMEM_SIZE - p;
        /*从用户空间写入数据*/
        if(copy_from_user(dev->mem + p, buf, count))
                ret = -EFAULT;
        else
        {
                *ppos += count;
                ret = count;
               
                printk(KERN_INFO "written %d bytes(s) from %d\n",count, p);
        }
       
        return ret;
}

/**/
static loff_t globalmem_llseek(struct file *filp, loff_t offset, int whence)
{
        loff_t newpos = 0;
       
        switch(whence)
        {
                case 0:   /* SEEK_SET */
                        newpos = offset;
                        break;
                case 1:   /* SEEK_CUR */
                        newpos = filp->f_pos + offset;
                        break;
                case 2:   /* SEEK_END */
                        newpos = filp->f_pos -1 + offset;
                        break;
                default:/* can't happen */
                        return -EINVAL;
        }
       
        if((newpos < 0)||(newpos > GLOBALMEM_SIZE))
                return -EINVAL;
       
        filp->f_pos = newpos;
        return newpos;
}

static const struct file_operations globalmem_fops =
{
        .owner = THIS_MODULE,
        .llseek = globalmem_llseek,
        .open = globalmem_open,
        .release = globalmem_release,
        .read = globalmem_read,
        .write = globalmem_write,
        .ioctl = globalmem_ioctl,
};

static int globalmem_init(void)
{
        int result;
        int err;
        dev_t devno = MKDEV(globalmem_major,0); /*得到设备编号*/
       
        /*申请设备号*/
        if(globalmem_major)
                result = register_chrdev_region(devno, 1, "globalmem");
        else
        {
                result = alloc_chrdev_region(&devno, 0, 1, "globalmem");
                globalmem_major = MAJOR(devno);
        }
        if(result < 0)
                return result;
       
        /*初始化cdev结构*/
        cdev_init(&globalmem_devp->cdev, &globalmem_fops);
        globalmem_devp->cdev.owner = THIS_MODULE;
        globalmem_devp->cdev.ops = &globalmem_fops;
       
        /*注册字符设备*/
        err = cdev_add(&globalmem_devp->cdev, devno, 1);
        if(err)
                printk(KERN_NOTICE "Error %d adding globalmem",err);
       
        /* 为设备描述结构分配内存*/
        globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
        if(!globalmem_devp) /*申请失败*/
        {
                result = -ENOMEM;
                goto fail_malloc;
        }
        memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
       
        return 0;
       
        fail_malloc:unregister_chrdev_region(devno, 1);
        return result;
}

void globalmem_exit(void)
{
        cdev_del(&globalmem_devp->cdev); /*注销cdev*/
        kfree(globalmem_devp); /*释放设备结构体内存*/
        unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); /*释放设备号*/
}

MODULE_AUTHOR("Jin huatian");
MODULE_LICENSE("GPL");

module_init(globalmem_init);
module_exit(globalmem_exit);

MagicBoy2010 发表于 2012-02-21 16:27

你程序里没用到malloc_sizes啊,你自己编译的内核模块?Makefile贴上来看看...

jlkmaster 发表于 2012-03-26 19:32

是的,自己编译的内核,后来又重新配置编译了内核后,可以加载成功!谢谢啊!

garbage哥 发表于 2014-08-21 21:10

朋友在 我遇到相同的问题我内核都重新编译过的还是有问题能帮忙一下吗

garbage哥 发表于 2014-08-21 21:10

朋友在 我遇到相同的问题我内核都重新编译过的还是有问题能帮忙一下吗

Tinnal 发表于 2014-08-23 22:00

回复 5# garbage哥

你又是插模块时告诉你,你模块里头有符号解析不了?
排查的方法为:

先把你插的模块缺的符号认下来。

cat /proc/kallsyms | grep "你记下来的模块"

如果找不到,就是证明你的内核没有编译这个函数进来。一般出现这个问题有两种可能。

1. 你编译模块所用的内核工程,和你目前所运行的内核不是一个版本。如果是这种问题,请重新编译你的内核,然后把机器里的内核换成新了,再次用户这个内核编译你的模块。
2. 你这个模块所依赖的函数,为另外一个模块导出,而此模块你当前并没有插入。如果是这样,你可以先把那个模块插入进去。如果不知道是那个模块,可以先在内核里搜索一下你记下来的函数名,找到.c文件后,看看Makefile把这个文件编译进哪个模块了。如果你的PC环境,也可以用户modprobe自动依赖的模块都探测出来,自动插入。


   
页: [1]
查看完整版本: Linux设备驱动详解globalmem驱动 求助