linux kernel —— 字符设备
cdev结构体
1. 在Linux内核中,使用cdev结构体描述一个字符设备, 其中比较重要的就是file_operation结构体, 它不仅能够实现打开本设备, 还能在当前设备的基础上打开其他的设备, 这一切都取决于再文件打开函数里定义的文件指针。
1 struct cdev { 2 struct kobject kobj; 3 struct module *owner; /*to which module it belongs*/ 4 struct file_operations *ops; /* file operation struct*/ 5 struct list_head list; 6 dev_t dev; /*device number*/ 7 unsigned int count; 8 };
cdev的struct中dev_t成员定义了设备号,为32位,其中主设备号有12位,次设备号有20位,用下列宏可以获取主次设备号:
1 MAJOR(dev_t dev) 2 MINOR(dev_t dev)
反过来,可以根据以下宏和已知的主次设备号生成dev_t:
MKDEV(int major, int minor)
2. linux内核提供了一组函数以用于操作cdev结构体:
void cdev_init(struct cdev *, struct file_operations *);/*初始化cdev成员,并建立cdev和file_operations之间的连接*/ struct cdev *cdev_alloc(void); /*动态申请一个cdev内存*/ void cdev_put(struct cdev *p); int cdev_add(struct cdev *, dev_t, unsigned); /*向设备添加一个cdev,注册*/ void cdev_del(struct cdev *); /*向系统删除一个cdev,注销*/
3. 在cdev结构体中的另一个重要成员是file_operations, 它定义了字符设备驱动提供给虚拟文件系统的接口函数(API)。
1 struct file_operations { 2 3 struct module *owner; 4 5 loff_t (*llseek) (struct file *, loff_t, int); 6 7 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 8 9 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 10 11 ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); 12 13 ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); 14 15 int (*iopoll)(struct kiocb *kiocb, bool spin); 16 17 int (*iterate) (struct file *, struct dir_context *); 18 19 int (*iterate_shared) (struct file *, struct dir_context *); 20 21 __poll_t (*poll) (struct file *, struct poll_table_struct *); 22 23 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 24 25 long (*compat_ioctl) (struct file *, unsigned int, unsigned long); 26 27 int (*mmap) (struct file *, struct vm_area_struct *); 28 29 unsigned long mmap_supported_flags; 30 31 int (*open) (struct inode *, struct file *); 32 33 int (*flush) (struct file *, fl_owner_t id); 34 35 int (*release) (struct inode *, struct file *); 36 37 int (*fsync) (struct file *, loff_t, loff_t, int datasync); 38 39 int (*fasync) (int, struct file *, int); 40 41 int (*lock) (struct file *, int, struct file_lock *); 42 43 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); 44 45 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); 46 47 int (*check_flags)(int); 48 49 int (*flock) (struct file *, int, struct file_lock *); 50 51 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); 52 53 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); 54 55 int (*setlease)(struct file *, long, struct file_lock **, void **); 56 57 long (*fallocate)(struct file *file, int mode, loff_t offset, 58 59 loff_t len); 60 61 void (*show_fdinfo)(struct seq_file *m, struct file *f); 62 63 ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, 64 65 loff_t, size_t, unsigned int); 66 67 loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in, 68 69 struct file *file_out, loff_t pos_out, 70 71 loff_t len, unsigned int remap_flags); 72 73 int (*fadvise)(struct file *, loff_t, loff_t, int); 74 75 } __randomize_layout;
Note:
1. any member of the structure which you do not explicitly assign will be initialized to NULL
by gcc.
2.Linux v5.6, the proc_ops
structure was introduced to replace the use of the file_operations
structure when registering proc handlers.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)