1. ioctl工作原理
1.1 引入目的
之前所学的控制led灯是用read和write来进行数据传输的,为了将对设备的控制和对设备的读写区分开,引入ioctl
1.2 对应关系
应用层
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
函数功能:对设备的控制
参数:
fd:被操作的文件描述符
request:设备的命令码
...:需要传递地址
内核层:
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
1.3 解析命令码
1.4 封装命令码
1.5 封装命令码宏
1.6 封装led灯命令码
2. 分步注册字符设备驱动
分步注册流程
分配对象
对象初始化
指定设备号
静态指定设备号
动态指定设备号
注销设备号
注册
注销
3. file结构体功能
3.1 inode结构体作用
只要有一个文件,在文件系统中存在,在应用层就会有一个inode号与之对应
在内核空间就会有一个struct inode结构体与之对应
所以说inode结构体起到上下级关联
3.2 应用层open-->底层open
应用层在open打开一个设备文件时,会返回一个文件描述符
通过这个文件描述符,就可以调用到底层的open函数
那应用层中的wirte/read函数,如何调用到底层的wirte/read函数
3.3 什么是文件描述符
fd文件描述符是在进程中调用open函数,返回的一个文件描述
每个进程都拥有自己唯一的一个文件描述符,并且文件描述符之间互相没有干扰
文件描述符是在进程中调用open函数函数返回的
所以在进程中可以找到这个文件描述符
在内核空间,通过task_struct结构体来描述打开进程的相关信息
所以在task_struct结构体可以找到文件描述符的相关信息
4. 私有数据传参
int myled_open(struct inode *inode, struct file *file)
{
int a = 50;
//错误 file->private_data = (void*)&a; //将a变量的地址,赋值给私有数据
file->private_data = (void*)a; //强转
return 0;
}
ssize_t myled_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
{
int a;
//错误 a = *(int*)file->private_data; //将私有数据内容,赋值给变量a
a = (int)file->private_data;//强转
return 0;
}