字符设备驱动模型
在字符设备中使用struct cdev这种结构来描述设备。
应用程序:读写文件,点灯;获取按键。用一些接口调用驱动程序去实现一些引用。
open这些函数,是C库实现的。从而进入内核,C库怎么进入内核?本质上,这些函数对应的汇编指令会引发一个异常,类似于中断一样,发生了就会进入相应的异常处理函数(进入到了内核空间)。根据发生异常的原因,调用不同的处理函数,比如sys_open,sys_read函数等 (内核的接口处就是系统调用的接口)。
最简单的莫过于led:
中间就依赖于驱动程序框架。
过程:
- 应用程序是有设备号的。应用程序会经过C库进入内核,内核最后会去调用驱动。
- 具体怎么通过内核找到驱动中的具体实现,就是框架中实现的。
- 在chrdev这个数组中找到file_operation这个 结构。这个结构是从驱动程序实现的。(驱动程序中就实现了这些led_open ,led_read ,led_write函数,以及file_operation结构体,这个结构体就有.open,指向我们写的led_open。)
- 然后入口函数这边,用register_chrdev函数,将结构体放到主设备号中。
file_operations 的结构体,此结构体就是 Linux 内核驱动操作函数集合。
驱动运行的方式有两种,其中有一种就是将驱动编译为模块,启动内核的时候,就使用命令加载驱动模块。这里就涉及到两个函数:
module_init(xxx_init); //注册模块加载函数 入口函数
module_exit(xxx_exit); //注册模块卸载函数 出口函数
字符设备注册和注销:
static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
static inline void unregister_chrdev(unsigned int major, const char *name)
一般字符设备的注册在入口函数中进行,字符设备的注销在出口函数中进行。
现在,我们可以看到已经定义了file_operations结构体,这个结构体就是设备的具体操作函数。现在就需要对用到的函数尽心初始化。比如open /realease/read/write。
附上面试题:
- TCP和UDP的区别?
- I2C驱动的框架
- 双链表怎么删除节点
- 编译的条件
- makefile的作用?gcc的作用?
- 代码生成可执行程序的过程?
- 中断切换的过程?
- 中断前的进程上下文保存在栈里,保存在哪个栈?
- 为什么有MMU,MMU有什么作用?
- 用过哪些系统调用,切换到内核态的接口API?
- 编译过程
- 链接分为哪些种类(动,静,装载时链接)
- 栈的大小由什么决定
- 栈的增长方式socket三种类型
- 内核中如何查找优先级
- MMU的简单介绍,具体实现
- new和malloc的区别
- 内核分配内存的方法
- 智能指针的底层实现
- 如何避免内存泄漏
- I2C和SPI 的区别
- 线程池和进程池的区别
- 同步与竞争
- 自旋锁和互旋锁的区别
- 数据结构中队列和栈的区别
- SD与EMMC。(汇川)
- PWM设置的流程
- SPI是全双吗?怎么判断
- CPU主频是多少
- 面向对象和面向过程的区别
- RTOS的实时性是如何保的
- CAN通信了解吗
- 内核管理硬件的方式
- 对缓存的理解
- SPI通信过程
- 对中断的理解。优先级反转用抢占不会乱掉吗
- ARM有多少个寄存器
- 字符设备有哪些?和块设备的区别