19 linux字符设备驱动
来源:互联网 发布:sql case when 多行 编辑:程序博客网 时间:2024/06/11 10:11
记得内核里是用面向对象的思想来实现的。但不是完全面向对象.
在linux内核里使用”struct cdev”类型的一个对象来描述一个字符设备驱动。
#include <linux/cdev.h>struct cdev { struct kobject kobj; //内核用于管理字符设备驱动, kobject就是内核里最底层的类. 内核里会自动管理此成员. struct module *owner; //通常设为THIS_MODULE, 用于防止驱动在使用中时卸载驱动模块 const struct file_operations *ops; //怎样操作(vfs), 也就是实现当用户进程进行open/read/write等操作时,驱动里对应的操作. struct list_head list; //内核链表节点,内核里自动管理此成员. dev_t dev; //设备号 unsigned int count; //设备数};
同时内核里也提供对cdev对象操作的函数:void cdev_init(struct cdev *, const struct file_operations *); //初始化cdev对象struct cdev *cdev_alloc(void); //动态分配一个cdev对象int cdev_add(struct cdev *, dev_t, unsigned); //设置cdev对象使用设备号及设备个数, 再把cdev对象增加到内核里,让它工作起来.void cdev_del(struct cdev *); //从内核里移除cdev对象
////////字符设备驱动实现的基本流程//////////
1. 申请设备号 register_chrdev_region(...);2. 声明一个cdev对象 struct cdev mycdev; 声明一个file_operations的文件操作对象 struct file_operations fops = { .owner = THIS_MODULE, .read = 读函数地址 .... };3. 初始化cdev对象,并把fops对象与cdev对象关联起来 cdev_init(&mycdev, &fops); //mycdev.ops = &fops; mycdev.owner = THIS_MODULE; 4. 把cdev对象加入内核里cdev_map(字符设备驱动的哈希表), 并指定该驱动对象的设备号 cdev_add(&mycdev, 设备号, 次设备号的个数);5. 卸载模块时, 要把设备驱动对象从内核里移除, 并把设备号反注册 unregister_chrdev_region(..); cdev_del(&mycdev);
////////////////////////////////////////////
测试代码test.c:
#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#define MYMA 1234#define MYMI 3344#define COUNT 3dev_t devid; //用于存放设备号struct cdev mycdev; int myopen(struct inode *ind, struct file *fl){ printk("in %s\n", __func__); return 0;}ssize_t myread(struct file *fl, char *__user buf, size_t len, loff_t *off){ printk("in %s\n", __func__); return 0;}ssize_t mywrite(struct file *fl, const char __user *buf, size_t len, loff_t *off){ printk("in %s\n", __func__); return len;}struct file_operations fops = { .owner = THIS_MODULE, .open = myopen, .read = myread, .write = mywrite,};static int __init test_init(void){ int ret; devid = MKDEV(MYMA, MYMI); //生成一个设备号 ret = register_chrdev_region(devid, COUNT, "mydev"); if (ret < 0) goto err0; //执行到这里,则有三个设备号(1234,3344), (1234, 3345), (1234, 3346) cdev_init(&mycdev, &fops); mycdev.owner = THIS_MODULE; ret = cdev_add(&mycdev, devid, COUNT); if (ret < 0) goto err1; return 0;err1: unregister_chrdev_region(devid, COUNT);err0: return ret;}static void __exit test_exit(void){ //使用完后需回收设备号 unregister_chrdev_region(devid, COUNT); cdev_del(&mycdev);}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");
///////////////////////////
编译加载驱动模块后,需要用”mknod /dev/设备文件名 c 主设备号 次设备号”来创建设备文件.
mknod /dev/mydev0 c 1234 3344mknod /dev/mydev1 c 1234 3345mknod /dev/mydev2 c 1234 3346然后可以写应用程序来操作设备文件,也可以用命令来简单地测试。cat /dev/mydev0 //会触发驱动里的open, read函数echo "kkk" > /dev/mydev0 //会触发驱动里的open, write函数.
阅读全文
1 0
- 19 linux字符设备驱动
- LINUX--字符设备驱动
- Linux字符设备驱动
- Linux字符设备驱动
- Linux字符设备驱动
- linux字符设备驱动
- linux字符设备驱动
- linux 字符设备驱动
- linux字符设备驱动
- linux 字符设备驱动
- Linux字符设备驱动
- linux字符设备驱动
- Linux字符设备驱动
- linux 字符设备驱动
- Linux字符设备驱动
- linux字符设备驱动
- Linux字符设备驱动
- Linux字符设备驱动
- 二叉搜索树转换为双向链表
- PHP哈希表碰撞攻击原理
- 开发者入门必读:最值得看的十大机器学习公开课
- Android存储---SQLite数据库存储
- 软考笔记0608
- 19 linux字符设备驱动
- TCP/IP协议简介
- 一个对象占用多少字节?
- 跨域资源共享 CORS 详解
- mongodb 在mac系统的设置和启动
- 信号执行的操作
- zookeeper Proposal 流程
- 关于PHP的错误机制总结
- 充电桩采用光耦隔离,更安全可靠