0

非常に単純なechoLinuxドライバーを作成しようとしています。

ドライバはコマンドラインから最大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;
    }
4

3 に答える 3

1

コードに少なくとも1つのエラーがあります:

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

それは不適切なopen()呼び出しです。
マニュアルページでopen()は、次のように指定しています。

アプリケーションは、以下の最初の3つの値(ファイルアクセスモード)の1つをoflagの値に正確に指定する必要があります。

O_RDONLY読み取り専用で開きます。
O_WRONLY書き込み専用で開きます。
O_RDWR読み取りおよび書き込み用に開きます。このフラグがFIFOに適用された場合、結果は未定義です。

1つだけを指定する代わりに、2つの値の式があります。

O_RDONLYとO_WRONLYは個別にビットであると思うので、O_RDONLY|のようになります。O_WRONLY = 10 | 01=11。読み取りと書き込みの両方のビットが設定されます。

これらの値を組み合わせることは許可されていないため、ビット値は関係ありません。
排他的な接尾辞「ONLY」を無視しているようです。
RDONLYは、「読み取りを許可し、書き込みを禁止する」という意味です。
WRONLYは、「書き込みを許可し、読み取りを禁止する」ことを意味します。
「O_RDONLY|O_WRONLY」は論理的な矛盾です。
読み取りと書き込みの両方を許可する場合は、O_RDWRを指定する必要があります。

また、Mark Stevensは、不適切な式がO_RDWRと同等ではないことを証明するために、正しい値とブール演算を提供しています。

于 2013-03-25T21:34:30.110 に答える
1

おがくずは正しい答えを出しましたが、コードに別の問題があります。

デバイスに250バイトを書き込む場合、バッファはnullで終了しません。次に、読み取るときに、strlenそれを超えて読み取り、予期しない結果につながります。

于 2013-03-27T08:56:38.143 に答える
0

書き込み関数を呼び出すたびに、バッファでmemsetが呼び出されます。これが、メッセージを取得できない根本的な原因です。

于 2013-08-27T05:34:22.997 に答える