gpt4 book ai didi

linux - 如何测试自己的 Linux 模块?

转载 作者:太空狗 更新时间:2023-10-29 11:13:55 25 4
gpt4 key购买 nike

今天我开始开发 Linux 模块。编写、编译和使用 Helloworld 相当困难,但我做到了。

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

很抱歉这个菜鸟问题,我用谷歌搜索过,但没有找到答案。抱歉英语不好。

最佳答案

一个基本的内核模块通常包括注册一个字符设备。简单的实现需要:

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

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

#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,因为循环可能会损害您的内核稳定性。

完成此操作后,您应该在用户空间 shell 中创建一个/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。

关于linux - 如何测试自己的 Linux 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26077140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com