2014-09-27 31 views
3

今天我開始開發Linux模塊。編寫,編譯和Helloworld工作相當困難,但我已經完成了。如何測試你自己的Linux模塊?

我的第二個模塊具有打開,寫入,讀取功能已準備就緒,但我真的不知道如何測試它。寫入方法只是使printk()。我的模塊被加載,它的名字是iamnoob。如何測試這個寫入(...)函數並在var/log/syslog中查找smth?cat> iamnoob只是將文件寫入目錄。與cp和其他相同。

對不起noob問題,我google了,但沒有找到答案。對不起,英語不好。

+0

如果你能給出解決問題的代碼,它將會有所幫助。此外,請檢查dmesg是否爲您的printk語句輸出。不知道,我也是Linux內核編程的新手。希望能幫助到你。 – 2014-09-29 18:33:04

回答

2

一個基本的內核模塊通常包括註冊一個字符設備。 簡單imlementation要求:具有特殊重要&次要

  • 註冊chrdev區域。
  • 分配文件操作結構並實現基本的讀/寫API。
  • 將具有文件操作結構的字符設備初始化並註冊到主要/次要區域。

參見下面的代碼段爲一個模塊的一個模板(只讀/寫的API imlemented):

#include <linux/module.h> 
#include <linux/fs.h> 
#include <linux/cdev.h> 
#include <linux/init.h> 
#include <linux/slab.h> 
#include <asm-generic/uaccess.h> 

#define MY_BUFFER_SIZE (1024 * 10) 
#define MY_CHRDEV_MAJOR 217 
#define MY_CHRDEV_MINOR 0 

static struct cdev my_cdev; 
static unsigned char *my_buf; 
static dev_t my_dev = MKDEV(MY_CHRDEV_MAJOR, MY_CHRDEV_MINOR); 

ssize_t my_read(struct file *file, char __user * buf, size_t count, loff_t * ppos) 
{ 
    int size; 

    size = MY_BUFFER_SIZE - 100 - (int)*ppos; 
    if (size > count) 
     size = count; 

    if (copy_to_user(buf, my_buf + *ppos, count)) 
     return -EFAULT; 

    *ppos += size; 
    return size; 
} 

ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 
{ 
    int size; 

    size = MY_BUFFER_SIZE - 100 - (int)*ppos; 
    if (size > count) 
     size = count; 

    if (copy_from_user(my_buf + *ppos, buf, count)) 
     return -EFAULT; 

    *ppos += size; 
    return size; 
} 

long my_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 
{ 
    printk ("%s!\n", __FUNCTION__); 
    return 0; 
} 

int my_mmap(struct file *f, struct vm_area_struct *vma) 
{ 
    printk ("%s!\n", __FUNCTION__); 
    return 0; 
} 
int my_open(struct inode *i, struct file *f) 
{ 
    printk ("%s!\n", __FUNCTION__); 
    return 0; 
} 
int my_release(struct inode *i, struct file *f) 
{ 
    printk ("%s!\n", __FUNCTION__); 
    return 0; 
} 

struct file_operations my_fops = 
{ 
    .owner = THIS_MODULE, 
    .read = &my_read, 
    .write = &my_write, 
    .unlocked_ioctl = &my_unlocked_ioctl, 
    .mmap = &my_mmap, 
    .open = &my_open, 
    .release = &my_release, 
}; 


static int __init my_module_init(void) 
{ 
    int line = 0; 
    unsigned char *pos; 

    printk ("%s!\n", __FUNCTION__); 
    my_buf = (unsigned char *)kzalloc(MY_BUFFER_SIZE, 0); 
    if (my_buf == NULL) { 
     printk("%s - failed to kzallocate buf!\n", __FUNCTION__); 
     return -1; 
    } 
    pos = my_buf; 
    while (pos - my_buf < MY_BUFFER_SIZE - 100) { 
     sprintf(pos, "Line #%d\n", line++); 
     pos += strlen(pos); 
    } 
    cdev_init(&my_cdev, &my_fops); 
    if (register_chrdev_region(my_dev, 1, "my_dev")) { 
     pr_err("Failed to allocate device number\n"); 
    } 
    cdev_add(&my_cdev, my_dev, 1); 
    printk ("%s - registered chrdev\n", __FUNCTION__); 
    return 0; 
} 

static void __exit my_module_exit(void) 
{ 
    printk ("my_module_exit.\n"); 
    unregister_chrdev_region(my_dev, 1); 
    return; 
} 
module_init(my_module_init); 
module_exit(my_module_exit); 
MODULE_LICENSE("GPL"); 

這個模塊使用一個緩衝器,用於文件操作,因此可以在任何機器上進行測試,而不管它的硬件。確保避免不必要的printk,因爲循環可能會損害內核的穩定性。

一旦做到這一點,在用戶空間的外殼,你應該創建一個的/ dev節點來代表你的性格設備:

sudo mknod /dev/[dev_name] c [major] [minor] 

例如:

sudo mknod /dev/my_dev c 217 0 

然後你就可以測試你的閱讀/寫入API:

sudo insmod my_modult.ko 
cat /dev/my_dev 
less -f /dev/my_dev 
sudo su 
root> echo "This is a test" > /dev/my_dev 
root> exit 
cat /dev/my_dev 

上面列出的shell命令執行讀取操作,然後以root身份登錄到允許寫入設備),寫入char dev,然後退出並再次閱讀以查看更改。

現在,您通常會根據需要實施ioctl和mmap。