设计字符设备
文件系统调用系统IO的内核处理过程
在Linux文件系统管理中,当应用程序调用open函数时,内核会根据文件路径找到文件的索引结点(inode),为文件分配文件描述符和文件对象,并根据打开模式和权限等参数进行相应的操作和设置。
硬件层原理
思路:把底层寄存器配置操作放在文件操作接口里,新建一个文件绑定该文件操作接口,应用程序通过操作指定文件来设置底层寄存器。
基本接口实现:查原理图,数据手册,确定底层需要配置的寄存器。类似于裸机开发。实现一个文件的底层操作接口,这是文件的基本特征。
struct file_operations存放在ebf-buster-linux/include/linux/fs.h。
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); int (*iterate_shared) (struct file *, struct dir_context *); __poll_t (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); unsigned long mmap_supported_flags; int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **, void **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); void (*show_fdinfo)(struct seq_file *m, struct file *f); #ifndef CONFIG_MMU unsigned (*mmap_capabilities)(struct file *); #endif ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int); int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t, u64); int (*dedupe_file_range)(struct file *, loff_t, struct file *, loff_t, u64); int (*fadvise)(struct file *, loff_t, loff_t, int); } __randomize_layout;
驱动层原理
把file_operations文件操作接口注册到内核,内核通过主次设备号来记录它。
构造驱动基本对象:struct cdev,里面记录具体的file_operations。
cdev_init() //把用户构建的file_operations结构体记录在内核驱动的基本对象
两个Hash表(帮助找到cdev结构体)
chrdevs:登记设备号。
__register_chrdev_region()
cdev_map->probe:保存驱动基本对象struct cdev。
cdev_add()
文件系统层原理
mknod + 主次设备号
构建一个新的设备文件,通过主次设备号在cdev_map中找到cdev->file_operations,把cdev->file_operations绑定到新的设备文件中。
到这一步,应用程序就可以使用open()、write()、read()等函数来控制设备文件了。
设备号的组成与哈希表
标签:进阶,struct,int,loff,unsigned,long,file,linux,设备 From: https://www.cnblogs.com/couvrir/p/17626647.html