Linux字符驱动

发布时间:2026/7/17 4:04:02
Linux字符驱动 Linux字符驱动1. 注册宏(module_init)module_init是Linux内核提供的驱动初始化入口宏用于注册驱动程序的初始化函数是驱动与内核之间的桥梁。编译为可加载模块#define module_init(initfn) \ static inline initcall_t __inittest(void) \ { return initfn; } \ int init_module(void) __attribute__((alias(#initfn)));工作原理使用GCC的 __attribute__((alias)) 创建init_module别名当用户执行insmod或modprobe加载模块时内核会查找并调用init_module函数使用方式static int __init xxx_module_init() { return 0; } // 指定函数为驱动入口函数 module_init(xxx_module_init);2. 注销宏(module_exit)module_exit 是 Linux 内核提供的 驱动卸载入口宏 用于注册驱动程序的清理函数。当用户执行 rmmod 命令卸载模块时内核通过此宏找到并执行驱动的退出逻辑。编译为可加载模块#define module_exit(exitfn) \ static inline exitcall_t __exittest(void) \ { return exitfn; } \ void cleanup_module(void) __attribute__((alias(#exitfn)));工作原理使用 GCC 的 __attribute__((alias)) 创建 cleanup_module 符号别名当用户执行 rmmod 卸载模块时内核会查找并调用 cleanup_module 函数使用方式static void __exit chrdevbase_exit(void) { } module_exit(chrdevbase_exit);3.设备操作函数结构体struct file_operations { struct module *owner; // 指向模块驱动的指针 loff_t (*llseek)(struct file *, loff_t, int); ssize_t (*read)(struct file *, char __user *, loff_t *); ... }该结构中包含指向用户空间的指针必须使用copy_to_user()访问以及各类回调函数需要的回调需要用户实现。如下所示// 定义open具体实现 static int chrdev_open(struct inode *inode, struct file *filp) { ... return 0; } // 定义write具体实现 static ssize_t chrdev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) { ... return 0; } // 定义release具体实现 static int chrdev_release(struct inode *inode, struct file *filp) { ... return 0; } // 定义read具体实现 static ssize_t chrdev_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) { ... return 0; } // 定义结构体变量chr_dev并对需要的回调进行赋值 static struct file_operations chr_dev { .owner THIS_MODULE, .open chrdev_open, .read chrdev_read, .write chrdev_write, .release chrdev_release, };