无法在echo内核模块中发现错误

时间:2013-03-25 20:15:40

标签: c linux linux-kernel driver

我正在尝试编写一个非常简单的echo Linux驱动程序。

驱动程序从命令行获取最多250个字符,然后将其写入虚拟设备“mydev”。这再次从设备读回。前端和驱动程序代码粘贴在下面以供参考。

问题是我能够写但不能阅读。编译或分段错误没有错误。但是没有打印出驱动程序读取中printk中的任何消息。我很困惑发生了什么事。我能在这里得到一些线索吗?

我只是为了更清晰而共享代码副本:

mydriver.c:

    #include <linux/module.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>

    MODULE_LICENSE("GPL");

    static int major;
    static char kbuf[250];

    static int dv_open(struct inode *inode, struct file *filp)
    {
        return 0; 
    }

    static int dv_close(struct inode *inode, struct file *filp)
    {
        return 0; 
    }

    static ssize_t dv_read(struct file *filp, char __user *buf, 
                    size_t sz, loff_t *fpos)
    {
        int r;
        int L;
        printk("READ:Entering\n");

        L = strlen(kbuf);
        r = copy_to_user(buf, kbuf, L);

        printk("READ:Ends\n");

        return L; 
    }
    static ssize_t dv_write(struct file *filp, const char __user *buf, 
                    size_t sz, loff_t *fpos)
    {
        int r, wr_sz;

        printk("WRITE:Entering\n");
        memset(kbuf,'\0', 250);
        if ( sz <= 250 ) {
           wr_sz = sz;
        } else {
           wr_sz = 250;
        }
        r = copy_from_user(kbuf, buf, wr_sz);

        printk("WRITE:Rx buf = %s\n", kbuf);

        return 0;

    }
    static struct file_operations dv_fops = {
        .open     = dv_open,
        .release  = dv_close,
        .read     = dv_read,
        .write    = dv_write,
        .owner    = THIS_MODULE,
    };

    int init_module(void)
    {
        major = register_chrdev(0, "dvdev", &dv_fops);
        if ( major < 0 ) {
           printk("Error in registering driver\n");
           return -1;
        }
        else printk("Success. major = %d\n", major);
        return 0;
    }

    void cleanup_module(void)
    {
        unregister_chrdev(major, "dvdev");
    }

myuserapp.c

    #include <stdio.h>
    #include <fcntl.h>
    #include <string.h>

    static char buf[250];
    static char * wbuf;
    int main(int argc, char **argv)
    {
        int fd;
        int option;
        int nbr = 0, len;

        if ( argc != 2 ) {
           printf("usage: front <devName>\n");
           return -1;
        }
        fd = open("mydev", O_RDONLY | O_WRONLY);
        if ( fd < 0 ) {
           printf("Error opening file. %s does not exist\n", argv[1]);
           return -2;
        }

        wbuf = argv[1];
        len = strlen(wbuf);
        nbr = write(fd, wbuf, len); 
        printf("USR: Buf written = %s, nbr = %d\n", wbuf ,nbr);


        nbr = read(fd, buf, 250);
        printf("USR RD: %s", buf);

        close(fd);
        return 0;
    }

3 个答案:

答案 0 :(得分:1)

您的代码至少有一个错误:

 fd = open("mydev", O_RDONLY | O_WRONLY);

这是一次不正当的open()电话 man page for open()指定:

  

应用程序应在oflag的值中指定下面前三个值(文件访问模式)中的一个:

     

O_RDONLY仅供阅读。
  O_WRONLY仅供写作。
  O_RDWR开放阅读和写作。如果将此标志应用于FIFO,则结果未定义。

不是只指定一个,而是有两个值的表达式。

  

我猜O_RDONLY和O_WRONLY分别是位,所以它会像O_RDONLY | O_WRONLY = 10 | 01 = 11。读取和写入两个位都已设置。

位值无关紧要,因为不允许组合这些值 你似乎忽略了“ONLY”的排除后缀 RDONLY表示“允许读取和禁止写入” WRONLY意味着“允许写入和禁止读取” “O_RDONLY | O_WRONLY”是一个逻辑矛盾 如果要允许读写,则必须指定O_RDWR。

Mark Stevens提供了正确的值和布尔算术来证明你的inproper表达式不等于O_RDWR。

答案 1 :(得分:1)

锯末给出了正确的答案,但你的代码中还有另一个问题。

如果向设备写入250个字节,则缓冲区不会以空值终止。然后,在阅读时,strlen将超越它,导致意外结果。

答案 2 :(得分:0)

对write函数的每次调用都将导致在缓冲区上调用memset。这是您无法检索消息的根本原因。