10.6字符驱动设备
1.字符设备驱动概念
字符设备是以字节流的形式进行顺序访问的设备。在linux操作系统中为字符设备编写的驱动程序就是字符设备驱动
2.字符设备的驱动注册注销
1.字符设备驱动注册函数
int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
这个函数注册成功后我们能够得到一个主设备号和256个次设备号,次设备号范围时0-255、 当驱动注册成功后,注册成功的驱动的主设备号和驱动的名字会保存在/proc/devices文件中
2.字符设备驱动注销函数
void unregister_chrdev(unsigned int major, const char *name)
字符设备驱动编写示例
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
unsigned int major; // 保存注册驱动得到的主设备号
// 封装各种操作方法
int mychrdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t mychrdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t mychrdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
int mychrdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
// 定义一个操作方法结构体变量并初始化
struct file_operations fops = {.open=mychrdev_open,.read=mychrdev_read,.write=mychrdev_write,.release=mychrdev_close,
};
// 入口函数,安装内核模块时执行
static int __init mycdev_init(void)
{printk(KERN_ERR "入口函数执行\n");major = register_chrdev(0, "mychrdev", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("注册字符设备驱动成功 major=%d\n", major);return 0;
}
// 出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{printk(KERN_DEBUG "出口函数执行\n");// 字符设备驱动的注销unregister_chrdev(major, "mcyhrdev");
}// 用于指定入口函数的地址
module_init(mycdev_init);
// 用于指定出口函数的地址
module_exit(mycdev_exit);
// 用于声明当前内核模块遵循“GPL”协议
MODULE_LICENSE("GPL");
用户空间和内核空间的数据传递
1.int copy_to_user(void __user volatile *to, const void *from,unsigned long n)
功能:从内核空间拷贝指定数量的数据到用户空间
2.unsigned long __must_checkcopy_from_user(void *to, const void __user *from, unsigned long n)
功能:从用户空间拷贝数据给内核空间
物理内存映射到虚拟内存的api
1.void __iomem *ioremap(phys_addr_t offset, size_t size)
功能:将指定大小的物理内存映射到虚拟内存
2. void iounmap(void __iomem *addr)
功能:取消物理内存的映射