自动创建节点
在前面的驱动程序中,当我们编写完一个驱动程序并安装后,我们还需要自己手动的使用mknod
命令创建一个节点,创建节点之前还需要知道设备的主设备号和次设备号,需要使用cat /proc/devices
来查看,如果每次编写驱动程序都需要进行这一系列操作的话,那实在是太麻烦了,下面就开始介绍在安装模块的时候能够自动进行设备节点创建的方法。
大概就是在入口函数中进行register_dev,class_create和device_create,在出口函数中进行device_destory,class_destroy,和unregister_dev,具体使用的代码如下:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
static struct class *hello_class;
static ssize_t hello_write (struct file *, const char __user *, size_t, loff_t *);
ssize_t hello_read (struct file *, char __user *, size_t, loff_t *);
static unsigned int major = 0;
static char kernel_buf[10];
static const struct file_operations hello_fops = {
.owner = THIS_MODULE,
.write = hello_write,
.read = hello_read,
};
int hello_init(void) {
printk("hello drv init\n");
major = register_chrdev(0, "hello_drv", &hello_fops);
hello_class = class_create(THIS_MODULE, "hello");
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello_dev");
return 0;
}
void hello_exit(void) {
printk("hello drv exit\n");
device_destroy(hello_class, MKDEV(major, 0));
class_destroy(hello_class);
unregister_chrdev(major, "hello_drv");
}
ssize_t hello_write (struct file *FILE, const char __user *buf, size_t len, loff_t * off) {
if(len > 10) return -1;
copy_from_user( kernel_buf, buf, len);
return len;
}
ssize_t hello_read (struct file *FILE, char __user * buf, size_t len, loff_t *off) {
copy_to_user(buf, kernel_buf, len);
return len;
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
下面的语句会在/sys/class下创建一个目录,名为hello,
hello_class = class_create(THIS_MODULE, "hello");
下面的语句会在hello目录下产生一个符号链接
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello_dev");
这两条语句配合使用就能直接创建一个node,名为hello_dev,当然别忘了在出口函数中调用相应的函数以删除对应的node。
在驱动程序中直接对硬件地址进行读写(驱动程序与硬件进行交互)
-
static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
ioremap函数可实现将物理地址映射到虚拟地址。使用这个函数后我们就可通过操作映射后的虚拟地址来间接操作物理地址。