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);
阅读(1714) | 评论(1) | 转发(0) |