今天我开始开发Linux模块。编写,编译和与Helloworld合作相当困难,但我已经完成了。
我的第二个模块具有开放,写入和读取功能,但我真的不知道如何测试它。 Write方法只是生成printk()。我的模块已加载,其名称为iamnoob。如何测试这个write(...)函数并在var / log / syslog中找到smth? 猫> iamnoob只是将文件写入目录。与cp和其他相同。
对于noob问题,我已经用谷歌搜索了,但没有找到答案。抱歉英语不好。
答案 0 :(得分:2)
基本内核模块通常包括注册字符设备。 简单的实现需要:
请参阅以下代码段作为模块的模板(仅读取/写入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命令执行read,然后以root身份登录(允许写入设备),写入char dev,然后退出并再次读取以查看更改。
现在,如果需要,您通常会实施ioctl和mmap。