从内核模块写入和读取设备文件的代码?

我已经多次尝试下面的代码。

#include<linux/module.h> #include<linux/kernel.h> #include<linux/fs.h> #include<linux/cdev.h> #include<asm/uaccess.h> #include<linux/semaphore.h> MODULE_LICENSE("DUAL BSD/GPL"); static int dev_open(struct inode *,struct file *); static int dev_release(struct inode *,struct file *); ssize_t dev_read(struct file *,char *, size_t ,loff_t *); ssize_t dev_write(struct file *,const char *,size_t ,loff_t *); static int major; int dev_major = 0; int dev_minor = 0; struct cdev *cdev; struct device { char array[100]; struct semaphore sem; }chr_arr; struct file_operations dev_ops = { .owner = THIS_MODULE, .read = dev_read, .write = dev_write, .open = dev_open, .release = dev_release }; ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *offset) { int i; i=copy_to_user(buf,chr_arr.array,count); printk(KERN_ALERT"buff:%s",buf); return i; } ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *offset) { //printk(KERN_ALERT"\nsorry,byebye"); int j; //msg_ptr = kmalloc(count,GFP_KERNEL); //for(j=0;j<count;j++) if(count>100) return -1; j = copy_from_user(chr_arr.array,buf,count); //printk(KERN_ALERT"msg_ptr:%s",msg_ptr); return j; } static int dev_open(struct inode *inode,struct file *filp) { filp->private_data = inode->i_cdev; if(down_interruptible(&chr_arr.sem)) { printk(KERN_INFO " could not hold semaphore"); return -1; } //printk(KERN_ALERT"ah ha the device is open !now we can go further"); return 0; } static int dev_release(struct inode *inode,struct file *filp) { up(&chr_arr.sem); //module_put(THIS_MODULE); return 0; } static int init_device(void) { int result; dev_t dev_no,dev; result = alloc_chrdev_region(&dev_no,0,1,"chr_dev"); if(result < 0) { printk("sorry no major number left"); return result; } major = MAJOR(dev_no); dev = MKDEV(major,0); cdev = cdev_alloc(); cdev->ops = &dev_ops; sema_init(&chr_arr.sem,1); printk("the major number allocated is %d\n",major); result = cdev_add(cdev,dev,1); if(result < 0 ) { printk(KERN_INFO "Unable to allocate cdev"); return result; } return 0; } static void clean_device(void) { cdev_del(cdev); unregister_chrdev_region(major,1); } module_init(init_device); module_exit(clean_device); 

但是它给了我下面的警告。

 CC [M] /home/karan/practice/scrw/scrw1.o In file included from /usr/src/linux-2.6.34.10-0.6/arch/x86/include/asm/uaccess.h:571:0, from /home/karan/practice/scrw/scrw1.c:4: In function 'copy_from_user',inlined from 'write' at /home/karan/practice/scrw/scrw1.c:43:6: /usr/src/linux-2.6.34.10-0.6/arch/x86/include/asm/uaccess_32.h:212:26: warning: call to 'copy_from_user_overflow' declared with attribute warning: copy_from_user() buffer size is not provably correct Building modules, stage 2. MODPOST 1 modules CC /home/karan/practice/scrw/scrw1.mod.o LD [M] /home/karan/practice/scrw/scrw1.ko 

然后当我尝试写回显你好> / dev / my_dev 30秒左右后屏幕会冻结。

问题是你应该返回read / write方法读/写的字节数,如果一切顺利,copy_ {from,to,_user()的返回值是0。 如果复制成功,则返回例如写入方法的计数:

 unsigned long ret; printk(KERN_INFO "Inside write \n"); if (count > sizeof(char_arr.array) - 1) return -EINVAL; ret = copy_from_user(char_arr.array, buff, count); if (ret) return -EFAULT; char_arr.array[count] = '\0'; return count; 

你也应该确保当你复制到你的缓冲区(如果你只想处理字符串)时会附加一个终止的'\ 0'字符。 如果它是你处理的二进制数据,那么将它的长度存储在你的结构中。

示例读取方法:

 ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *offset) { int len = count >= strlen(chr_arr.array) ? strlen(chr_arr.array) : count; if (*offset >= strlen(chr_arr.array)) return 0; if (copy_to_user(buf,chr_arr.array,len)) return -EFAULT; return len; } 

编辑:搞砸了示例代码,修复它。

编辑2:示例读取方法。