从内核模块写入和读取设备文件的代码?
我已经多次尝试以下代码。
#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
然后当我尝试写 echo hi > 时/dev/my_dev 屏幕在 30 秒左右后冻结。
I have tried the following code many times .
#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);
but its giving me the following warning.
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
and then when I try to write echo hi > /dev/my_dev the screen freezes after 30 secs or so.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是你应该在读/写方法中返回读/写的字节数,如果一切顺利的话copy_{from,to}_user()的返回值为0。如果复制成功,则在写入方法中返回例如计数:
您还应该确保在复制到缓冲区时附加终止“\0”字符(如果您只想处理字符串)。如果它是二进制数据,您也将其长度存储在结构中。
示例读取方法:
编辑:弄乱了示例代码,修复它。
Edit2:示例读取方法。
The problem is that you should return the number of bytes read/written in your read/write methods, the return value of copy_{from,to}_user() is 0 if everything goes well. Return e.g. count in your write method if copying succeeds:
You should also make sure that a terminating '\0' character is appended when you copy to your buffer (if you'd like to deal only with strings). If it is binary data you deal with store its length in your struct as well.
An example read method:
Edit: messed up example code, fixing it.
Edit2: example read method.