2013-03-25 66 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) – 2013-03-25 20:25:24

+0

是的,讀取+寫入 – Aadishri 2013-03-25 20:33:59

+1

好吧,我卡在一臺Windows電腦上,或者我會試用它,但那可能就是這樣。 RDWR == 2,但(RD | WR)==(0 | 1)== 1 == WRONLY。所以我猜想用「O_RDONLY | O_WRONLY」打開文件只會打開它。 – 2013-03-25 20:44:20

回答

1

您的代碼已經到了t一個錯誤:

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.

位值是不相關的,因爲不允許組合這些值。
你好像忽略了排除後綴「ONLY」。
RDONLY的意思是「允許讀取和禁止寫入」。
WRONLY表示「允許寫入和禁止讀取」。
「O_RDONLY | O_WRONLY」是一個邏輯矛盾。
如果您想允許讀取和寫入,則必須指定O_RDWR。

馬克史蒂文斯提供了正確的值和布爾運算來證明你的不正確的表達式不等於O_RDWR。

+0

這是事實,因爲[馬克史蒂文斯](http://stackoverflow.com/users/1684497/mark-stevens)第一次評論。但是,如果這是他的問題,那麼他不應該寫任何東西? 'fd'只是用戶空間的一個數字;所以內核必須是bug,並返回一個文件句柄。另外,我認爲這至少部分取決於驅動程序的open()來執行此操作,目前他沒有做任何事情,但值得檢查。 – 2013-03-25 21:58:52

+1

通常,O_RDONLY爲0,O_WRONLY爲1,O_RDWR爲2.如果這些是實際值,則「O_RDONLY | O_WRONLY == O_WRONLY'。 – 2013-03-25 22:01:20

+1

@artlesnoise - 我的觀點是,無論這些值如何,用戶的open()調用都不符合手冊頁。即使這些價值觀像OP所想的那樣,這仍然是一個矛盾的表達。手冊頁沒有列出不正確訪問規範的錯誤編號,可能是因爲布爾結果無效(無論如何)。 – sawdust 2013-03-25 22:08:09

1

木屑給出了正確的答案,但是在你的代碼中還有另一個問題。

如果您向設備寫入250個字節,則緩衝區不是空終止的。然後,在閱讀時,strlen會超出它,導致意想不到的結果。

+0

是的,你是正確的邊界條件錯誤。 – Aadishri 2013-03-28 09:38:03

0

每次調用您的寫入函數都會導致在緩衝區中調用memset。這是您無法檢索該消息的根本原因。

+0

你能舉一個例子嗎??會讓你的回答更好... – NREZ 2013-08-27 05:55:05