2013-03-25 3 views
0

Я пытаюсь написать очень простой драйвер echo Linux.Не удалось обнаружить ошибку в модуле ядра echo

Водитель берет максимум 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

Почему вы открыли файл только для чтения и только для записи? Вы имели в виду чтение/запись? (O_RDWR) –

+0

Да, прочитайте + напишите – Aadishri

+1

Ну, я застрял на компьютере под управлением Windows или попробую, но это может быть так. RDWR == 2, но (RD | WR) == (0 | 1) == 1 == WRONLY. Поэтому я предполагаю, что открытие файла с «O_RDONLY | O_WRONLY» открывает его только для записи. –

ответ

1

Ваш код имеет в аренду т одна ошибка:

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

Это ненадлежащей open() вызов.
man page for open() указывает, что:

Applications shall specify exactly one of the first three values (file access modes) below in the value of oflag:

O_RDONLY Open for reading only.
O_WRONLY Open for writing only.
O_RDWR Open for reading and writing. The result is undefined if this flag is applied to a FIFO.

Вместо указания только один, у вас есть выражение двух значений.

I guess O_RDONLY and O_WRONLY are bits individually, so it would be something like O_RDONLY | O_WRONLY = 10|01 = 11 . Both the bits of Read and write are set.

Значения бит не имеют значения, поскольку объединение этих значений не допускается.
Вы, кажется, игнорируете исключающий суффикс «ТОЛЬКО».
RDONLY означает «разрешить чтение и запрет записи».
WRONLY означает «разрешить запись и запретить чтение».
«O_RDONLY | O_WRONLY» - логическое противоречие.
Если вы хотите разрешить чтение и запись, вам необходимо указать O_RDWR.

И Марк Стивенс предоставил правильные значения и булевскую арифметику, чтобы доказать, что ваше inproper выражение не эквивалентно O_RDWR.

+0

Это верно, поскольку [Mark Stevens] (http://stackoverflow.com/users/1684497/mark-stevens) впервые прокомментировал. Однако, если это его проблема, тогда он ничего не должен писать? 'Fd' - это просто номер для пользовательского пространства; поэтому ядро ​​должно быть ошибкой и вернуть дескриптор файла. Кроме того, я думаю, что это, по крайней мере, частично до 'open()' драйвера, чтобы реализовать это, и в настоящее время он ничего не делает, но стоит проверить. –

+1

Классически, O_RDONLY равно 0, O_WRONLY равно 1, а O_RDWR равно 2. Если это фактические значения, 'O_RDONLY | O_WRONLY == O_WRONLY'. –

+1

@artlesnoise - Моя точка зрения заключается в том, что независимо от этих значений вызов 'open()' пользователя не соответствует справочной странице. Даже если бы значения были похожи на ОП, это все еще противоречивое выражение. На странице руководства не указан номер ошибки для неправильной спецификации доступа, возможно, потому что результат Boolean не является недопустимым (в этом случае так или иначе). – sawdust

1

опилки дали правильный ответ, но есть еще одна проблема в вашем коде.

Если вы пишете 250 байт на ваше устройство, буфер не заканчивается на нуль. Затем, прочитав, strlen будет читать дальше, что приведет к неожиданному результату.

+0

да, вы правы на ошибке граничного условия. – Aadishri

0

Каждый вызов вашей функции записи приведет к вызову memset в буфере. Это основная причина, по которой вы не можете получить сообщение.

+0

Можете ли вы привести пример ...? Сделает ваш ответ лучше ... – NREZ

Смежные вопросы