前言
linux三大设备驱动
杂项设备
cat/proc/misc
cat/proc/devices
杂项设备描述结构体
cd/usr/src/linux-headers-4.18.0-15viinclude/linux/miscdevice.h
structmiscdevice{ intminor;//次设备号 constchar*name;//设备节点名称(如/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){ //在内核里面无法使用基础c库printf,需要使用内核库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,//这个宏是动态分配次设备号,避免冲突 .name="register_hongPangZi_misc,//设备节点名称 .fops=misc_fops,//这个变量记住,自己起的,步骤二使用}
步骤二:填充file_operations结构体
structfile_operationsmisc_fops{ .owner=THIS_MODULE}
步骤三:注册杂项设备并生成设备节点
staticintregisterMiscDev_init(void){ //在内核里面无法使用基础c库printf,需要使用内核库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){ //在内核里面无法使用基础c库printf,需要使用内核库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,//这个宏是动态分配次设备号,避免冲突 .name="register_hongPangZi_misc",//设备节点名称 .fops=&misc_fops,//这个变量记住,自己起的,步骤二使用};staticintregisterMiscDev_init(void){ //在内核里面无法使用基础c库printf,需要使用内核库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
入坑
入坑一:编译报错,结构体之后未加分号
问题
解决
入坑二:编译错误,文件操作指针问题
问题
解决