请帮我制作这个假字符linux设备驱动程序

时间:2014-04-29 12:45:42

标签: linux module character driver device

您好我正在尝试使用以下方法写入假的char设备驱动程序:

echo>的/ dev /

并使用以下方式阅读:

cat / dev /

我的问题是,当我使用上面提到的" cat"进行阅读时,我会不断获得在终端上打印的第一个字符。使用上面的echo方法写入后读取方法。

我的目标是将整个字符集写回驱动程序...

我正在为此目的使用动态内存分配,但是在尝试多种方法重写驱动程序中的read()和write()代码后却没有得到最终结果。请帮忙..

我的Makefile是正确的...(我使用的是内核版本为2.6.33的ubuntu ...)

我的代码如下:

#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

static dev_t first;
static struct cdev c_dev;
static struct class *cl;
static char* k_buf = NULL;

static int my_open(struct inode *i,struct file *f)
{
    printk(KERN_INFO "In driver open()\n");
    return 0;
}

static int my_close(struct inode *i,struct file *f)
{
    printk(KERN_INFO "In driver close()\n");
    return 0;
}

static ssize_t my_read(struct file *f,char __user *buf,size_t len,loff_t *off)
{
    printk(KERN_INFO "In driver read()\n");

    if(k_buf == NULL)
    {
        printk(KERN_INFO "You cannot read before writing!\n");
        return -1;
    }

    while(*k_buf != 'EOF')
    {
        if(copy_to_user(buf,k_buf,1))
            return -EFAULT;
        off++;
        return 1;
    }

    return 0;
}

static ssize_t my_write(struct file *f,const char __user *buf,size_t len,loff_t *off)
{
    printk(KERN_INFO "In driver write()\n");
    k_buf = (char*) kmalloc(sizeof(len),GFP_KERNEL);

    if(copy_from_user(k_buf,buf,len))
        return -EFAULT;

    off += len;

    return (len);
}

static struct file_operations fops =
{
    .owner = THIS_MODULE,
    .open = my_open,
    .release = my_close,
    .read = my_read,
    .write = my_write
};

static int __init rw_init(void) /*Constructor*/
{
    printk(KERN_INFO "hello: rw_ch_driver registered\n");

    if(alloc_chrdev_region(&first,0,1,"krishna") < 0)
    {
        return -1;
    }

    if ((cl = class_create(THIS_MODULE,"chardev")) == NULL)
    {
        unregister_chrdev_region(first,1);
        return -1;
    }

    if (device_create(cl,NULL,first,NULL,"rw_char_driver") == NULL)
    {
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

    cdev_init(&c_dev,&fops);

    if(cdev_add(&c_dev,first,1) == -1)
    {
        device_destroy(cl,first);
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

return 0;
}

static void __exit rw_exit(void)/*destructor*/
{
    cdev_del(&c_dev);
    device_destroy(cl,first);
    class_destroy(cl);
    unregister_chrdev_region(first,1);
    printk(KERN_INFO "bye rw_chardriver unregistered");
}

module_init(rw_init);
module_exit(rw_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("krishna");
MODULE_DESCRIPTION("read write character driver");

1 个答案:

答案 0 :(得分:0)

仔细查看my_read()中的while循环。

最重要的是首先注意:你不需要这个循环。你已经在其中添加了 return 语句,因此它永远不会执行多次,因为当达到返回时整个函数将退出。看起来你试图让函数重复一次返回一个字节,但是你应该只调用 copy_to_user 一次,并将它想要返回给用户的字节数传递给它代替。如果你只发送一个字符就好了。由用户再次进行读取调用以获取下一个字符。

copy_to_user的好处是,它的返回代码会告诉你它是否因为数组边界错误而失败,所以不需要检查每个字符的EOF。事实上,当你从缓冲区读取时,你不会将'EOF'作为一个角色,因为it doesn't exist。你的缓冲区将存储字符,通常是一个空终止符'\ 0',但C中没有'EOF'字符.EOF是一个你需要识别自己并向任何调用open的人报告的状态。对于“cat”命令,这是通过从read返回0来完成的。话虽这么说,你仍然应该检查你的数组边界,所以我们不会得到另一个HeartbleedThis SO answer对于如何进行边界检查以确保不发送比缓冲区更多的字节有一个很好的建议。

另外,请给[这篇文章(https://meta.stackexchange.com/questions/981/syntax-highlighting-language-hints)一个读数。如果您的问题标签中没有您的语言,则其他读者可以对您的标记进行标记。我已经编辑了你的问题以进行清理,所以你现在可以点击“编辑”以查看我是如何做到的。