北辰苏州网站建设,文化馆的网站怎么建设,佛山网站制作公司,学网页制作的网站1 字符设备驱动框架 1.1字符设备 定义#xff1a;只能以一个字节一个字节的方式读写的设备#xff0c;不能随机的读取设备中中的某一段数据#xff0c;读取数据需要按照先后顺序。#xff08;字符设备是面向字节流的#xff09; 常见的字…1 字符设备驱动框架 1.1字符设备 定义只能以一个字节一个字节的方式读写的设备不能随机的读取设备中中的某一段数据读取数据需要按照先后顺序。字符设备是面向字节流的 常见的字符设备鼠标 键盘 串口 控制台 块设备可以从设备的任意位置读取一定长度数据的设备。 常见的块设备硬盘 磁盘 光盘 U盘 SD卡 tf卡。。 1.2字符设备驱动框架 init流程--》HelloModule { 1 申请设备号静态申请 动态申请 2 创建一个字符设备 3 初始化字符设备 4 将设备号和字符设备关联起来 } exit流程--》HelloExit { 1 删除字符设备 2 删除设备号 } 买车 1 申请车牌号静态申请 动态申请 陕U.88888 2 买车 3 将车牌号和车关联起来 卖车 1 卖车 2 注销车牌号 1.2.1设备号 定义设备号是设备在内核中的身份和标识是内核区分不同设备的唯一信息设备号是由主设备号和次设备号构成主设备号表示一类设备次设备号表示该类设备中的某一个设备。 设备号是一个32bit的无符号整数高12bit是主设备号低20bit是次设备号。 《linux/kdev_t.h》 #define MINORBITS 20 #define MINORMASK ((1U MINORBITS) - 1) #define MAJOR(dev) ((unsigned int) ((dev) MINORBITS)) #define MINOR(dev) ((unsigned int) ((dev) MINORMASK)) #define MKDEV(ma,mi) (((ma) MINORBITS) | (mi)) 1.2.2申请设备号 申请设备号有两种方式静态申请 动态申请 静态申请设备号 int register_chrdev_region(dev_t from, unsigned count, const char *name) 作用静态申请设备号 from设备号由主次设备号构成 count子设备个数 *name设备名称 返回值0 成功 非0 失败 void unregister_chrdev_region(dev_t from, unsigned count) 作用从内核中移除设备号 from设备号由主次设备号构成 count子设备个数 动态申请设备号 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) 作用动态申请设备号 *dev:指向设备号的指针 baseminor子设备的第一个编号 count子设备个数 *name设备名称 返回值0 成功 非0 失败 1.2.3创建字符设备 struct cdev *cdev_alloc(void) 作用创建一块用于存放字符设备的空间 返回值是指向创建成功的字符设备的指针 在Linux内核中用struct cdev来描述一个字符设备 struct cdev { struct kobject kobj;--》内嵌的内核对象 struct module *owner;--》该字符设备所在的内核模块的对象指针 const struct file_operations *ops;--》指向操作字符设备的方法集 struct list_head list;--》用来将已向内核注册的所有字符设备形成链表 dev_t dev;--》设备号由主设备号和次设备号构成 unsigned int count;--》隶属于同一个主设备号的次设备个数 }; void cdev_del(struct cdev *p) 作用删除字符设备 *p指向字符设备的指针 1.2.4初始化字符设备--》绑定驱动方法 void cdev_init(struct cdev *cdev, const struct file_operations *fops) 作用初始化字符设备 *cdev指向字符设备的指针 *fops指向操作字符设备的函数集的指针 1.2.5将字符设备和设备号关联 int cdev_add(struct cdev *p, dev_t dev, unsigned count) 作用将字符设备和设备号关联并将字符设备添加到内核中 *p指向字符设备的指针 dev设备号 count子设备的个数 返回值成功为0 失败非0 测试步骤 1 sudo insmod hello.ko 2 dmesg |tail --250 0 3 cat /proc/devices--查看设备号 250 0 4 sudo mknod /dev/haha0 c 250 0 5 ls -l /dev/haha*---查看创建字符设备文件 6 sudo ./test--open hahao ok! 7 dmesg |tail--helloopen/helloClose 8 sudo rmmod hello.ko 9 sudo rm /dev/haha0 区分字符设备驱动框架中使用的三个结构体 struct file:代表内核中一个打开的文件。系统中每个打开的文件在内核中都有一个关联的struct file。 struct inode:用来记录文件在物理上的信息。它和打开文件struct file结构不同一个文件可以对应多个struct file但是只有一个struct inode. struct file_operations:是内核给用户提供的驱动接口函数集用户可以定义函数集中的任何驱动方法。对于不支持的一般不写 字符设备文件--》250 0--字符设备(helloopen/helloclose) mice-----------鼠标 sudo cat mice 2 实现用户空间和内核空间的数据拷贝 用户代码对字符设备的任何操作最终都要落实到设备对应的底层操作函数上 内核空间--》用户空间 read--HelloRead 用户空间--》内核空间 write--》HelloWrite 应用层 fdopen(/dev/haha0) read(fd,) close(fd) 驱动层 增加HelloRead ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); char g_buf[]hellotest----; ssize_t HelloRead(struct file *pFile,char __user *buf,size_t count,loff_t *p) { copy_to_userbuf,g_buf,count; } unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) 作用从内核空间向用户空间拷贝数据 *to用户空间指针 *from内核空间指针数据源 n拷贝的字节数 copy_from_user 测试步骤: 1 sudo insmod hello.ko 2 dmesg |tail 3 sudo mknod /dev/haha0 c 250 0 4 ls -l /dev/hah* 5 sudo ./test--查看是否读到数据 6 sudo rmmod hello 7 sudo rm /dev/haha0