字符设备驱动的内部实现:
文件存在文件系统中,会有一个标识inode号,基于这个标识找到了struct_inode结构体(保存当前文件信息),struct_inode结构体中有一个struct cdev *i_cdev类型的字符设备指针,这个指针指向当前驱动对象struct cdev结构体 (字符设备驱动对象结构体)/(设备号是驱动存在内核的标识,也是设备驱动和设备文件关联的纽带),而这个结构体存放有struct file_operations *ops 操作方法结构体指针;接着基于这个struct file_operations *ops 操作方法结构体指针,找到了操作方法 mycdev_open()、mycdev_read()、mycdev_write()、mycdev_close();在操作方法里回调mycdev_open(用户层)
虚拟文件系统层:帮助用户根据系统调用函数,去调用底层不同的文件系统(包括驱动的文件系统);当调用open 时,虚拟文件系统中:存在sys open()
1、根据open传递的文件路径找到文件的inode结构体
2、根据inode结构体找到文件对应的驱动的对象指针
3、根据驱动对象指针找到驱动对象中的操作方法结构体指针
4、回调操作方法中的open
文件描述符:
一个进程可以多次调用open打开多个文件,计算机中同时存在大量进程,而这些进程可能会打开各种各样的文件,所以系统中在任何时刻都可能存在大量已经打开的文件,操作系统的功能之一就是文件管理(对这些打开的文件进行管理)。
底层中描述文件的数据结构叫做struce file,一个文件对应一个struct file(大量的文件就有大量的struct file),我们只需将这些数据结构用双链表连接起来,对文件的管理就变成了对双链表的增删改查,已经被打开的文件属于某个特定的进程,需要建立进程和文件的对应关系。
每一个进程都有一个task_strut,这个task_struct会指向一个struct files_struct结构体,这个结构体里会有一个指针数组struct file* fd_array[32],而这个指针数组就是文件描述符对应的数组。
————————————————
既然是数组就有下标,下标从0开始依次递增,task_struct结构里会有一个指针变量指向这个struct files_struct结构体,我们这个指针数组中的每个数据都是一个指针变量。打开的文件描述符都对应一个struct file的结构体,结构体里有描述该文件属性的相关信息,而这些struct file文件结构体之间,是通过双链表的形式链接起来的。
————————————————
inode结构体的作用
只有有一个文件在文件系统上存在,在内核空间就是有一个inode结构体
记录这个文件的信息。并且inode能够实现上下级关联。
文件描述符到底是什么?
当使用open函数打开一个文件的时候,就会产生一个文件描述符,这个文件描述符
以后就可以用来操作文件。它是一个大于0的整数,在一个进程内文件描述符的默
认最大值是1024.每个进程都拥有自己的文件描述,进程和进程间的文件描述符没有
干扰。如果想知道文件描述到底是什么,需要在进程中找到文件描述符存储的位置。
struct task_struct //描述进程的结构体
{
volatile long state; //进程的状态
int on_cpu;//表示进程在那个处理器上执行的
int prio; //进程的优先级
pid_t pid; //进程号
struct task_struct *real_parent; //父进程
struct signal_struct *signal; //进程处理信号
struct files_struct *files; //打开文件相关的结构体
};
struct files_struct {
struct file * fd_array[NR_OPEN_DEFAULT]; //结构体指针数组
};
//fd:其实就是fd_array的数组下标
file结构体的功能?
只要在进程内打开一次文件,在内核中就产生了一个file的结构体,这个结构体就是
用来记录打开文件时候的各种信息的结构体。将这个结构体放在fd_array数组中,这个
数组的下标就是返回给你的文件描述符。
struct file {
struct path f_path; //文件的路径
const struct file_operations *f_op; //操作方法结构体
unsigned int f_flags; //open的第二个参数就被赋值给了f_flags变量
fmode_t f_mode; //文件的权限
void *private_data; //私有数据,可以实现函数间传参
}