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

时间:2012-01-28 19:34:22

标签: c linux linux-kernel driver kernel-module

我多次尝试过以下代码。

#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&gt; / dev / my_dev屏幕在30秒左右冻结。

1 个答案:

答案 0 :(得分:6)

问题是您应该返回读/写方法中读/写的字节数,如果一切顺利,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;
}

编辑:弄乱了示例代码,修复它。

Edit2:示例读取方法。