《驅動學習 —— 雜項裝置》
阿新 • • 發佈:2020-10-21
1.雜項裝置
雜項裝置,本質上就是字元裝置驅動,只不過是一個特殊一點的。雜項裝置的主裝置號,被固定在 10,通過次裝置號進行區分裝置。雜項設備註冊之後,在 /dev/ 目錄下就有 name 裝置節點,在 /sys/clas/misc 下面,也會自動生成的類資訊,因此,一定程度上,比標準的的字元裝置驅動簡單了。
2.雜項裝置的註冊與登出
註冊:
int misc_register(struct miscdevice * misc)
登出:
int misc_deregister(struct miscdevice *misc)
可以看到,基本就是圍繞著miscdevice結構體。
struct miscdevice { int minor; const char *name; // 名字 const struct file_operations *fops; // 檔案操作結構體 struct list_head list; struct device *parent; struct device *this_device; const char *nodename; mode_t mode; };
結構體中,name 是註冊的名字,以後將會在 /dev 目錄下,進行顯示的 name,裡面最主要的是 struct file_operations ,在註冊雜項裝置的時候,字元裝置的結構體與雜項裝置進行繫結,minor 為 MISC_DYNAMIC_MINOR 的時候,miscdevice 核心層會自動尋找一個空閒的次裝置號。
3.雜項裝置驅動編寫流程
struct const file_operations xxxx_fops = { .unlock_ioctl = xxx_ioctl, xxxx }; struct miscdevice xxx_dev = { .minor = MISC_DYNAMIC_MINOR, .name = “xxx”, .fops = xxxx_fops }; static int __init xxx_init() { return misc_register(&xxx_dev ); } void __exit xxx_exit() { return misc_deregister(&xxx_dev) ; }
當呼叫 misc_register(&xxx_dev ); 的時候,會在 misc_open 的幫助下,實現將 xxx_dev 成為 file 的private_data,也就是 系統會幫助我們實現 file->private_data = xxx_dev。
4.例項
#include <linux/init.h> #include <linux/module.h> /*驅動註冊的標頭檔案,包含驅動的結構體和註冊和解除安裝的函式*/ #include <linux/platform_device.h> /*註冊雜項裝置標頭檔案*/ #include <linux/miscdevice.h> /*註冊裝置節點的檔案結構體*/ #include <linux/fs.h> #define DRIVER_NAME "hello_ctl" #define DEVICE_NAME "hello_ctl123" MODULE_LICENSE("Dual BSD/GPL"); static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){ printk("cmd is %d,arg is %d\n",cmd,arg); return 0; } static int hello_release(struct inode *inode, struct file *file){ printk(KERN_EMERG "hello release\n"); return 0; } static int hello_open(struct inode *inode, struct file *file){ printk(KERN_EMERG "hello open\n"); return 0; } static struct file_operations hello_ops = { .owner = THIS_MODULE, .open = hello_open, .release = hello_release, .unlocked_ioctl = hello_ioctl, }; static struct miscdevice hello_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &hello_ops, }; static int hello_probe(struct platform_device *pdv){ printk(KERN_EMERG "\tinitialized\n"); misc_register(&hello_dev); return 0; } static int hello_remove(struct platform_device *pdv){ printk(KERN_EMERG "\tremove\n"); misc_deregister(&hello_dev); return 0; } static void hello_shutdown(struct platform_device *pdv){ ; } static int hello_suspend(struct platform_device *pdv,pm_message_t pmt){ return 0; } static int hello_resume(struct platform_device *pdv){ return 0; } struct platform_driver hello_driver = { .probe = hello_probe, .remove = hello_remove, .shutdown = hello_shutdown, .suspend = hello_suspend, .resume = hello_resume, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, } }; static int hello_init(void) { int DriverState; printk(KERN_EMERG "HELLO WORLD enter!\n"); DriverState = platform_driver_register(&hello_driver); printk(KERN_EMERG "\tDriverState is %d\n",DriverState); return 0; } static void hello_exit(void) { printk(KERN_EMERG "HELLO WORLD exit!\n"); platform_driver_unregister(&hello_driver); } module_init(hello_init); module_exit(hello_exit);