how to write on a device file using copy_from_user()
Hi ,
I am new to linux and was making a module in which user can read as well as write to a device file.the following is my code where read is working fine but not the write function. Code:
MODULE_LICENSE("DUAL BSD/GPL"); regards karan |
Read following char device code. It will help you correct error in your driver.
http://www.de-brauwer.be/wiki/wikka....haracterDevice. |
In your kmalloc you are allocating memory just enough to hold a char pointer, I think you need to change that may be something like
kamlloc(20* sizeof(char),GFP_KERNEL) See if this helps http://tuxthink.blogspot.com/2010/10...m-scratch.html |
still there is a problem
hi bsat and nini09
hi have gone through your links and had made changes like kamlloc(20* sizeof(char),GFP_KERNEL) and copy_from_user(msg_ptr,buf,count). but still theer is the same problem . could please reply any more suggestions regards karan |
What is the problem you are facing now ? could you show the complete code of your module ?
|
hi bsat
after i got a link from you i changed my code accordingly .but still there is the same problem, My code is as follow: #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); return 0; //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; } /*dev_t dev =0; dev_major = register_chrdev(dev,"chr_dev",&dev_ops); printk(KERN_ALERT"MAJOR NUMBER IS:%d and minor is:%d",dev_major,dev_minor);*/ return 0; } static void clean_device(void) { //dev_t devno = MKDEV(dev_major, dev_minor); //printk(KERN_ALERT"removing MAJOR NUMBER IS:%d and removing minor is:%d",dev_major,dev_minor); cdev_del(cdev); unregister_chrdev_region(major,1); } module_init(init_device); module_exit(clean_device); and then when i do insmod rwd.ko, mknod /dev/chr_dev c 249 0 , echo hi > /dev/chr_dev the screen hangs after few seconds. Really thanks for your intrest. regards karan |
In your init function there two calls to registration
Quote:
Quote:
|
hi bsat
yes....but second one is commented by /*...*/(dev_major = register_chrdev(dev,"chr_dev",&dev_ops);). regards karan |
oh ok did not see that sorry.
Please make sure you are using the right major number, it might be different every time you insert. Are you sure the number is 249 ? |
Do you read scull_write function in the example code?
|
Hi nini09 and bsat
I have following the book ldd (and i think this example is taken from there). its bit complex. i just wanted to see how we can use copy_to_user and copy_from_user for reading and writing . I have solved my problem of writing function as now i am return count and putting last bit to null in array. it is as follow what i have done. ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *offset) { unsigned int ret; if(count > sizeof(chr_arr.array) - 1) return -EINVAL; ret = copy_from_user(chr_arr.array,buf,count); if(ret) return -EFAULT; chr_arr.array[count] = '\0'; printk(KERN_ALERT"the ptr:: %p",offset); printk(KERN_ALERT"the ptr after::%p",offset); return count; } but now the problem lies in read function now whenever i try to cat /dev/my_dev it runs for infintely.further for bsat, i have checked the major numbers from /var/log/messages and its not a problem. further any help would be great. regards karan |
The issue of read function is that returning value always isn't zero.
|
Hi nini09 and bsat
thanks .....now its working regards karan |
hi karan,
I am also working on this .could you please post your final solution. it would be a great help. |
What's your questions?
|
All times are GMT -5. The time now is 01:05 PM. |