免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3602 | 回复: 5
打印 上一主题 下一主题

Linux设备驱动详解globalmem驱动 求助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-31 23:15 |只看该作者 |倒序浏览
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[GLOBALMEM_SIZE]; /*全局内存*/
};



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);

论坛徽章:
0
2 [报告]
发表于 2012-02-21 16:27 |只看该作者
你程序里没用到malloc_sizes啊,你自己编译的内核模块?Makefile贴上来看看...

论坛徽章:
0
3 [报告]
发表于 2012-03-26 19:32 |只看该作者
是的,自己编译的内核,后来又重新配置编译了内核后,可以加载成功!谢谢啊!

论坛徽章:
0
4 [报告]
发表于 2014-08-21 21:10 |只看该作者
朋友  在 我遇到相同的问题  我内核都重新编译过的  还是有问题  能帮忙一下吗

论坛徽章:
0
5 [报告]
发表于 2014-08-21 21:10 |只看该作者
朋友  在 我遇到相同的问题  我内核都重新编译过的  还是有问题  能帮忙一下吗

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
6 [报告]
发表于 2014-08-23 22:00 |只看该作者
回复 5# garbage哥

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

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

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

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

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


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP