如何测试自己的Linux模块? [英] How to test your own Linux module?

查看:79
本文介绍了如何测试自己的Linux模块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我开始开发Linux模块.用Helloworld编写,编译和使用它相当困难,但是我已经做到了.

Today I am getting started with developing Linux modules. It was rather hard to write, compile and work with Helloworld, but I've done it.

第二个具有打开,写入,读取功能的模块已经准备就绪,但是我真的不知道如何对其进行测试. Write方法只是使printk().我的模块已加载,其名称为iamnoob.如何测试此write(...)函数并在var/log/syslog中找到smth? cat> iamnoob只是将文件写入目录.与cp和其他相同.

My second module with open, write, read functions is ready, but I really dont know how to test it. Write method just makes printk(). My module is loaded, its name is iamnoob. How to test this write(...) function and to find smth in var/log/syslog? cat > iamnoob just writes a file to the dir. Same with cp and other.

对不起,我已经用谷歌搜索了一个菜鸟问题,但没有找到答案.对不起,英语不好.

Sorry for noob question, i've googled, but no answer has been found. Sorry for poor English.

推荐答案

基本内核模块通常包括注册字符设备. 简单的实现要求:

A basic kernel module would normally include registering a character device. Simple imlementation requires:

  • 用特定的主&注册chrdev区域未成年人.
  • 分配文件操作结构并实现基本的读/写API.
  • 使用文件操作结构将字符设备初始化并注册到主要/次要区域.

请参阅以下代码段作为模块的模板(仅实现读/写API):

See the following code snippet as a template of a module (only read / write APIs are 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,因为循环可能会损害内核稳定性.

This module uses a buffer for file operations, therefore can be tested on any machine, regardless of its HW. Make sure you avoid unnecessary printk's as loops may harm your kernel stability.

一旦完成,在用户空间外壳中,您应该创建一个/dev节点来代表您的角色设备:

Once this is done, in user-space shell you should create a /dev node to represent your character device:

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

例如:

sudo mknod /dev/my_dev c 217 0

然后,您可以使用以下方法测试您的读/写API:

Then you can test your read / write APIs with:

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,然后退出并再次读取以查看更改.

The shell commands listed above perform read, then login as root (to allow writing to device), write to the char dev, then exit and read again to see the changes.

现在,如果需要,通常可以实现ioctl和mmap.

Now you'd normally implement ioctl and mmap if needed.

这篇关于如何测试自己的Linux模块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆