_Linux杂项驱动.ppt
《_Linux杂项驱动.ppt》由会员分享,可在线阅读,更多相关《_Linux杂项驱动.ppt(57页珍藏版)》请在三一办公上搜索。
1、杂项(misc)驱动,设备结点,应用程序控制驱动的链接ttyS0/ttyUSB0设备结点创建Mknod驱动自动创建,ls-l/dev/ttySAC*crw-rw-rw-1 root tty 204,64 Mar 20 09:39/dev/ttySAC0crw-rw-rw-1 root tty 204,65 Mar 20 2000/dev/ttySAC1crw-rw-rw-1 root tty 204,66 Mar 20 2000/dev/ttySAC2crw-rw-rw-1 root tty 204,67 Mar 20 2000/dev/ttySAC3,杂项(misc)驱动,传统的驱动分为字符
2、设备和块设备.字符设备硬件收到数据直接发送给应用程序,而块设备带了一个缓冲。杂项设备可以看字符设备驱动的特例。杂项一般开小硬件的模块的驱动.杂项指主设备统一为10,不同硬件用从设备区别的。杂项设备的编程接口相对是最为简单。,ls-l/dev/|grep 10crw-rw-1 root root 10,250 Mar 20 2000 s3c-cmmcrw-rw-1 root root 10,220 Mar 20 2000 s3c-g2dcrw-rw-1 root root 10,249 Mar 20 2000 s3c-g3dcrw-rw-1 root root 10,254 Mar 20 200
3、0 s3c-jpgcrw-rw-1 root root 10,252 Mar 20 2000 s3c-mfccrw-rw-1 root root 10,253 Mar 20 2000 s3c-ppcrw-rw-1 root root 10,230 Mar 20 2000 s3c-rotator,驱动与应用程序接口,驱动要全部或者部分实现下面接口,当应用程序执行调用时,内核会调驱动相应的接口函数。open readwritecloseIoctllseekmmap,struct file_operations struct module*owner;loff_t(*llseek)(struct f
4、ile*,loff_t,int);ssize_t(*read)(struct file*,char _user*,size_t,loff_t*);ssize_t(*write)(struct file*,const char _user*,size_t,loff_t*);ssize_t(*aio_read)(struct kiocb*,const struct iovec*,unsigned long,loff_t);ssize_t(*aio_write)(struct kiocb*,const struct iovec*,unsigned long,loff_t);int(*readdir)
5、(struct file*,void*,filldir_t);unsigned int(*poll)(struct file*,struct poll_table_struct*);int(*ioctl)(struct inode*,struct file*,unsigned int,unsigned long);long(*unlocked_ioctl)(struct file*,unsigned int,unsigned long);long(*compat_ioctl)(struct file*,unsigned int,unsigned long);int(*mmap)(struct
6、file*,struct vm_area_struct*);int(*open)(struct inode*,struct file*);int(*flush)(struct file*,fl_owner_t id);int(*release)(struct inode*,struct file*);int(*fsync)(struct file*,struct dentry*,int datasync);int(*aio_fsync)(struct kiocb*,int datasync);int(*fasync)(int,struct file*,int);int(*lock)(struc
7、t file*,int,struct file_lock*);ssize_t(*sendpage)(struct file*,struct page*,int,size_t,loff_t*,int);unsigned long(*get_unmapped_area)(struct file*,unsigned long,unsigned long,unsigned long,unsigned long);int(*check_flags)(int);int(*dir_notify)(struct file*filp,unsigned long arg);int(*flock)(struct f
8、ile*,int,struct file_lock*);ssize_t(*splice_write)(struct pipe_inode_info*,struct file*,loff_t*,size_t,unsigned int);ssize_t(*splice_read)(struct file*,loff_t*,struct pipe_inode_info*,size_t,unsigned int);int(*setlease)(struct file*,long,struct file_lock*);,无杂项设备还是字符设备必须要定义一个file_operations,并且把自己对应处
9、理函数放入相应的成员。比如open处理函数放open成员close处理函数放入release成员file_operations可以部分实现,关于file_operations调用,struct file*对于应用程序 int fd;当应用程序执行open().它会在系统调用的机制在内核调用do_sys_open().由它创建struct file*并且返回fd给应用程序。在它最后一步,如果驱动实现 file_operations.open.它也将调这个函数指针,SYSCALL_DEFINE3(open,const char _user*,filename,int,flags,int,mode)
10、long ret;if(force_o_largefile()flags|=O_LARGEFILE;ret=do_sys_open(AT_FDCWD,filename,flags,mode);/*avoid REGPARM breakage on x86:*/asmlinkage_protect(3,ret,filename,flags,mode);return ret;,关open参数的含义,int leds_open(struct inode*node,struct file*filp)来源于inode=dentry-d_inode;struct dentry是该文件在内存的文件树的一个描
11、述该文件结点dentry又是由文件系统的nd-path.dentry来初始化 nd-path.dentry 又是由 path-dentry;(path_to_nameidata)error=do_path_lookup(dfd,pathname,LOOKUP_PARENT,/path.dentry设定,当应用程序调用close,在最开始调用file_operations.release接口。,leds驱动的write接口,假设向驱动写入一个整数,leds根据整数来亮灭.比如0 x9=(1001)2 表示第1灯亮,第2,3灭,第4灯亮.,Leds_write实现,static struct fi
12、le_operations leds_oper=.owner=THIS_MODULE,/标准写法,表示打开这个文件的模块是谁.write=leds_write,;,static ssize_t leds_write(struct file*filp,const char _user*buf,size_t buf_len,loff_t*offset)unsigned int val;if(buf_len!=4)return-1;val=*(unsigned int*)buf);printk(KERN_DEBUG leds_write:%dn,val);leds(val);return buf_l
13、en;,file_operations注册,杂项使用如下定义注册,struct miscdevice int minor;/杂项设备从设备号,主设备号固定为10const char*name;/杂项设备名字,同时也是设备结点文件名const struct file_operations*fops;/文件操作struct list_head list;struct device*parent;struct device*this_device;extern int misc_register(struct miscdevice*misc);extern int misc_deregister(s
14、truct miscdevice*misc);,杂项设备,static struct miscdevice leds_misc=.minor=LEDS_MINOR,.name=hxyled,.fops=,static int _init mymod_init(void)int i;printk(KERN_INFOhello,this is my first leds drivern);misc_register(,应用程序代码,arm-linux-gcc test/test_leds.c-o test_leds,#define DEVICE_NAME/dev/hxyledint main()u
15、nsigned int i,val;int fd=open(DEVICE_NAME,O_RDWR);if(fd=-1)printf(open file%s failuren,DEVICE_NAME);return-1;for(i=0;i100;i+)val=0 x9;printf(test_leds:write%dn,val);write(fd,(void*),驱动测试,1。装入驱动 insmod mymod.ko2.如果udev工作正常,则会自动创建/dev/hxyled,如果没有 mknod/dev/hxyled c 10 220还有一种情况是从设备号与已安装的驱动冲突,也不会创建设备结点
16、3.测试leds,./test_leds4.移载驱动 rmmod mymod,Open流程,1.应用程序执行 open()int open(const char*pathname,int flags,mode_t mode);2.内核会切换到SWI状态,执行do_sys_open()long do_sys_open(int dfd,const char _user*filename,int flags,int mode)3.在do_sys_open()执行 do_filp_open()做真正的打开动作4.执行驱动的open()nameidata_to_filp()-_dentry_open()
17、从中取得f_ops的open指针,执行驱动的open代码,/fs/open.c:_dentry_open f-f_op=fops_get(inode-i_fop);file_move(f,open测试,rooturbetter 06#insmod mymod.kohello,this is my first leds driverrooturbetter 06#./test_ledstest_leds:write 9test_leds:write 6test_leds:write 9test_leds:write 6test_leds:write 9test_leds:write 6test_
18、leds:write 9Crooturbetter 06#dmesg|tailhello,this is my first leds driver/-mymod_init leds_open/-leds_open leds_write:9 leds_write:6 leds_write:9 leds_write:6 leds_write:9 leds_write:6 leds_write:9 leds_close/-leds_close,Module_init与file_operation.open的有什么区别?Module_init的是在安装时执行,是全局性的初始化。file_operati
19、on.open是每次打开一个文件实例的初始化,关于_user,_kernel,在LINUX每一个用户进程有4G的虚拟空间。_user就是应用程序里空间的地址。在驱动里操作是内核空间。,驱动,用户进程,Test_leds.c,val;,write,buf,Mymod.c,驱动的段错误,如果驱动直接使用用户空间的地址,如果不加检查,用户空间地址将会造成驱动的段错误,有时甚至破坏内核.write(fd,(void*)0 x123,4);/?-写入一个非法地址,如何防范非法地址?,内核规定,如果与_user空间交换数据,必须要 copy_from_user()和copy_to_user()copy_f
20、rom_user从user空间拷贝数据static inline unsigned long _must_check copy_from_user(void*to,const void _user*from,unsigned long n)copy_to_user 向user空间拷贝数据.这两个函数都首先调用access_ok来对内存做检查,如果合法才做真正的拷贝动作。,内存安全的写法,static ssize_t leds_write(struct file*filp,const char _user*buf,size_t buf_len,loff_t*offset)unsigned int
21、 val;if(buf_len!=4)return-1;/val=*(unsigned int*)buf);/非法地址会造成段错误 copy_from_user(void*),关于_must_check,在内核里如果由_must_check修饰的函数,它的返回值必须要检测,否则编译器为是错误比如直接写copy_from_user(warning:ignoring return value of copy_from_user,declared with attribute warn_unused_result必须写成,if(copy_from_user(,Ioctl的用法,Ioctl-io co
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- _Linux 杂项 驱动
链接地址:https://www.31ppt.com/p-2602732.html