前言
linux三大設備驅動
雜項設備
cat/proc/misc
cat/proc/devices
雜項設備描述結構體
cd/usr/src/linux-headers-4.18.0-15viinclude/linux/miscdevice.h
structmiscdevice{ intminor;//次設備號 constchar*name;//設備節(jié)點名稱(如/dev/ttyS8,則ttyS是名稱) conststructfile_operations*fops;//文件操作集(非常重要) structlist_headlist; structdevice*parent; structdevice*this_device; conststructattribute_group**groups; constchar*nodename; umode_tmode;};
雜項設備文件操作集
cd/usr/src/linux-headers-4.18.0-15viinclude/linux/fs.h
structfile_operations{ structmodule*owner; loff_t(*llseek)(structfile*,loff_t,int); ssize_t(*read)(structfile*,char__user*,size_t,loff_t*); ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*); ssize_t(*read_iter)(structkiocb*,structiov_iter*); ssize_t(*write_iter)(structkiocb*,structiov_iter*); int(*iterate)(structfile*,structdir_context*); int(*iterate_shared)(structfile*,structdir_context*); __poll_t(*poll)(structfile*,structpoll_table_struct*); long(*unlocked_ioctl)(structfile*,unsignedint,unsignedlong); long(*compat_ioctl)(structfile*,unsignedint,unsignedlong); int(*mmap)(structfile*,structvm_area_struct*); unsignedlongmmap_supported_flags; int(*open)(structinode*,structfile*); int(*flush)(structfile*,fl_owner_tid); int(*release)(structinode*,structfile*); int(*fsync)(structfile*,loff_t,loff_t,intdatasync); int(*fasync)(int,structfile*,int); int(*lock)(structfile*,int,structfile_lock*); ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int); unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong); int(*check_flags)(int); int(*setfl)(structfile*,unsignedlong); int(*flock)(structfile*,int,structfile_lock*); ssize_t(*splice_write)(structpipe_inode_info*,structfile*,loff_t*,size_t,unsignedint); ssize_t(*splice_read)(structfile*,loff_t*,structpipe_inode_info*,size_t,unsignedint); int(*setlease)(structfile*,long,structfile_lock**,void**); long(*fallocate)(structfile*file,intmode,loff_toffset, loff_tlen); void(*show_fdinfo)(structseq_file*m,structfile*f);#ifndefCONFIG_MMU unsigned(*mmap_capabilities)(structfile*);#endif ssize_t(*copy_file_range)(structfile*,loff_t,structfile*, loff_t,size_t,unsignedint); int(*clone_file_range)(structfile*,loff_t,structfile*,loff_t, u64); ssize_t(*dedupe_file_range)(structfile*,u64,u64,structfile*, u64);}__randomize_layout;
驅動編寫空模板準備
cd~/work/drivecp-arfhellowolrdregisterMiscDev
cdregisterMiscDev/rm*.ko*.o*.order*.symvers
mvhelloworld.cregisterMiscDev.c
#include<linux/init.h>#include<linux/module.h>staticintregisterMiscDev_init(void){ //在內(nèi)核里面無法使用基礎c庫printf,需要使用內(nèi)核庫printk printk("Hello,I’mhongPangZi,registerMiscDev_init\n"); return0;}staticvoidregisterMiscDev_exit(void){ printk("bye-bye!!!\n");}MODULE_LICENSE("GPL");module_init(registerMiscDev_init);module_exit(registerMiscDev_exit);
雜項設備注冊流程Demo
步驟一:填充miscdevice結構體
#include<linux/miscdevice.h>#include<linux/fs.h>
structmiscdevicemisc_dev{ .minor=MISC_DYNAMIC_MINRO,//這個宏是動態(tài)分配次設備號,避免沖突 .name="register_hongPangZi_misc,//設備節(jié)點名稱 .fops=misc_fops,//這個變量記住,自己起的,步驟二使用}
步驟二:填充file_operations結構體
structfile_operationsmisc_fops{ .owner=THIS_MODULE}
步驟三:注冊雜項設備并生成設備節(jié)點
staticintregisterMiscDev_init(void){ //在內(nèi)核里面無法使用基礎c庫printf,需要使用內(nèi)核庫printk printk("Hello,I’mhongPangZi,registerMiscDev_init\n"); intret=0; ret=misc_register(misc_dev); if(ret<0) { printk("Failedtomisc_register(misc_dev)\n"); return-1; } return0;}
staticintregisterMiscDev_init(void){ //在內(nèi)核里面無法使用基礎c庫printf,需要使用內(nèi)核庫printk printk("Hello,I’mhongPangZi,registerMiscDev_init\n"); intret=0; ret=misc_register(&misc_dev); if(ret<0) { printk("Failedtomisc_register(misc_dev)\n"); return-1; } return0;}
#include<linux/init.h>#include<linux/module.h>#include<linux/miscdevice.h>#include<linux/fs.h>structfile_operationsmisc_fops={ .owner=THIS_MODULE,};structmiscdevicemisc_dev={ .minor=MISC_DYNAMIC_MINOR,//這個宏是動態(tài)分配次設備號,避免沖突 .name="register_hongPangZi_misc",//設備節(jié)點名稱 .fops=&misc_fops,//這個變量記住,自己起的,步驟二使用};staticintregisterMiscDev_init(void){ //在內(nèi)核里面無法使用基礎c庫printf,需要使用內(nèi)核庫printk printk("Hello,I’mhongPangZi,registerMiscDev_init\n"); intret=0; ret=misc_register(&misc_dev); if(ret<0) { printk("Failedtomisc_register(&misc_dev)\n"); return-1; } return0;}staticvoidregisterMiscDev_exit(void){ misc_deregister(&misc_dev); printk("bye-bye!!!\n");}MODULE_LICENSE("GPL");module_init(registerMiscDev_init);module_exit(registerMiscDev_exit);
步驟四:編譯make
make
步驟五:加載卸載驅動測試
sudoinsmodregisterMiscDev.ko
dmesg
sudormmodregisterMiscDev.ko
入坑
入坑一:編譯報錯,結構體之后未加分號
問題
解決
入坑二:編譯錯誤,文件操作指針問題
問題
解決