Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55707
  • 博文数量: 15
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 55
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-01 09:50
文章分类
文章存档

2014年(1)

2013年(7)

2012年(8)

分类: Python/Ruby

2012-06-13 15:59:02

 Linux字符设备驱动-globalmem驱动编译加载遇到的问题及解决办法 2011-06-29 20:14 250人阅读 评论(0) 收藏 举报  代码是直接复制《LINUX设备驱动开发详解》里面的(源代码见下面)。  Makefile如下:  [c-sharp] view plaincopy      obj-m := globalmem.o        KERNELBUILD := /lib/modules/`uname -r`/build       default:           make -C $(KERNELBUILD) M=$(shell pwd) modules       clean:           rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions       make时遇到错误:  [c-sharp] view plaincopy      /home/shake/driverVBOX/globalmem.c:172:3: error: unknown field ‘ioctl’ specified in initializer    问题是由于2.6.36内核之后 去掉了原来的ioctl,添加两个新的成员,所以会出错 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); 所以修改源文件中file_operations内 .ioctl 改为 .compat_ioctl 即可     [c-sharp] view plaincopy      /home/shake/driverVBOX/globalmem.c:208:3: error: implicit declaration of function ‘kmalloc’       /home/shake/driverVBOX/globalmem.c:227:3: error: implicit declaration of function ‘kfree’      是缺少了一个头文件 #include   insmod globalmem.ko再次遇到问题:  [c-sharp] view plaincopy      insmod: error inserting 'globalmem.ko': -1 Device or resource busy     运行命令: cat /proc/devices  [c-sharp] view plaincopy      Character devices:         1 mem         4 /dev/vc/0         4 tty         4 ttyS         5 /dev/tty         5 /dev/console         5 /dev/ptmx         5 ttyprintk         6 lp         7 vcs        10 misc        13 input        21 sg        29 fb        99 ppdev       108 ppp       116 alsa       128 ptm       136 pts       180 usb       189 usb_device       226 drm       251 hidraw       252 usbmon       253 bsg       254 rtc              Block devices:         1 ramdisk       259 blkext         7 loop         8 sd         9 md        11 sr        65 sd        66 sd        67 sd        68 sd        69 sd        70 sd        71 sd       128 sd       129 sd       130 sd       131 sd       132 sd       133 sd       134 sd       135 sd       252 device-mapper       253 pktcdvd       254 mdp    发现源文件中  [c-sharp] view plaincopy      #define GLOBALMEM_MAJOR 254 /*预设的globalmem的主设备号*/     此设备号被占用,更换设备号即可加载。           globalmem.c  [c-sharp] view plaincopy      /*======================================================================          A globalmem driver as an example of char device drivers                     The initial developer of the original code is Baohua Song          . All Rights Reserved.      ======================================================================*/       #include        #include        #include        #include        #include        #include        #include        #include        #include        #include        #include        ////////增加此头文件//////////       #include        ////////////////////////////       #define GLOBALMEM_SIZE  0x1000  /*全局内存最大4K字节*/       #define MEM_CLEAR 0x1  /*清0全局内存*/       //#define GLOBALMEM_MAJOR 254    /*预设的globalmem的主设备号*/       #define GLOBALMEM_MAJOR 255    /*预设的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 *inodep, 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 count ?  - ENXIO: 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 count ?  - ENXIO: 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;       }              /* seek文件定位函数 */       static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)       {         loff_t ret = 0;         switch (orig)         {           case 0:   /*相对文件开始位置偏移*/             if (offset < 0)             {               ret =  - EINVAL;               break;             }             if ((unsigned int)offset > GLOBALMEM_SIZE)             {               ret =  - EINVAL;               break;             }             filp->f_pos = (unsigned int)offset;             ret = filp->f_pos;             break;           case 1:   /*相对文件当前位置偏移*/             if ((filp->f_pos offset) > GLOBALMEM_SIZE)             {               ret =  - EINVAL;               break;             }             if ((filp->f_pos offset) < 0)             {               ret =  - EINVAL;               break;             }             filp->f_pos = offset;             ret = filp->f_pos;             break;           default:             ret =  - EINVAL;             break;         }         return ret;       }              /*文件操作结构体*/       static const struct file_operations globalmem_fops =       {         .owner = THIS_MODULE,         .llseek = globalmem_llseek,         .read = globalmem_read,         .write = globalmem_write,         //.ioctl 改为 .compat_ioctl         .compat_ioctl = globalmem_ioctl,         .open = globalmem_open,         .release = globalmem_release,       };              /*初始化并注册cdev*/       static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)       {         int err, devno = MKDEV(globalmem_major, index);                cdev_init(&dev->cdev, &globalmem_fops);         dev->cdev.owner = THIS_MODULE;         dev->cdev.ops = &globalmem_fops;         err = cdev_add(&dev->cdev, devno, 1);         if (err)           printk(KERN_NOTICE "Error %d adding LED%d", err, index);       }              /*设备驱动模块加载函数*/       int globalmem_init(void)       {         int result;         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;                    /* 动态申请设备结构体的内存*/         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));                  globalmem_setup_cdev(globalmem_devp, 0);         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("Song Baohua");       MODULE_LICENSE("Dual BSD/GPL");              module_param(globalmem_major, int, S_IRUGO);              module_init(globalmem_init);       module_exit(globalmem_exit);
阅读(1670) | 评论(1) | 转发(0) |
0

上一篇:没有了

下一篇:using namespace std用法详解

给主人留下些什么吧!~~

sijialgc2012-09-19 15:12:35

公兴搬场 上海公兴搬场 公兴搬场公司 http://gxbcgs.com