




免费预览已结束,剩余1页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux驱动开发学习的一些必要步骤1. 学会写简单的makefile2. 编一应用程序,可以用makefile跑起来3. 学会写驱动的makefile4. 写一简单char驱动,makefile编译通过,可以insmod, lsmod, rmmod. 在驱动的init函数里打印hello world, insmod后应该能够通过dmesg看到输出。5. 写一完整驱动, 加上read, write, ioctl, polling等各种函数的驱动实现。 在ioctl里完成从用户空间向内核空间传递结构体的实现。6. 写一block驱动, 加上read,write,ioctl,poll等各种函数实现。7. 简单学习下内存管理, 这个是最难的,明白各种memory alloc的函数实现细节。这是Linux开发的基本功。8. 学习锁机制的应用,这个不是最难的但是最容易犯错的,涉及到很多同步和并发的问题。9. 看内核中实际应用的驱动代码。 你会发现最基本的你已经知道了, 大的框架都是一样的, 无非是read, write, ioctl等函数的实现, 但里面包含了很多很多细小的实现细节是之前不知道的。 这时候就要考虑到很多别的问题而不仅仅是基本功能的实现。 推荐您看2.6.20中integrated的一个驱动 kvm, 记得是在driver/lguest下,很好玩的, 就是Linux下的虚拟机驱动, 代码不长,但功能强大。有能力的可以自己写一操作系统按照要求做成磁盘镜像加载到虚拟机中, 然后客户机可以有自己的4G虚拟地址空间。10. 看完驱动欢迎您进入Linux kernel学习中来。 最简单的方法,跟着ldd(Linux devive driver)做一遍。1、 Makefile 是如何编写eg: # 这是上面那个程序的 Makefile 文件 1main:main.o mytool1.o mytool2.o 2gcc -o main main.o mytool1.o mytool2.o 3main.o:main.c mytool1.h mytool2.h 4gcc -c main.c 5mytool1.o:mytool1.c mytool1.h 6gcc -c mytool1.c 7mytool2.o:mytool2.c mytool2.h 8gcc -c mytool2.c9分析:在 Makefile 中也#开始的行都是注释行.Makefile 中最重要的是描述文件的依赖关系的说 明.一般的格式是: Linux 操作系统 C 语言编程入门 target: components /表示的是依赖关系TAB rule/规则main:main.o mytool1.o mytool2.o表示我们的目标(target)main 的依赖对象(components)是 main.o mytool1.o mytool2.o 当倚赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令.就象我们的上 面那个 Makefile 第3行所说的一样要执行 gcc -o main main.o mytool1.o mytool2.o (注意规则一行中的 TAB表示那里是一个 TAB 键)Makefile 有三个非常有用的变量.分别是$,$,$代表的意义分别是: $-目标文件;$-所有的依赖文件;$list); 5 cdev-kobj.ktype = &ktype_cdev_default; 6 kobject_init(&cdev-kobj); 7 cdev-ops = fops; /*将传入的文件操作结构体指针赋值给cdev的ops*/ 8 cdev_alloc()函数用于动态申请一个cdev内存1 struct cdev *cdev_alloc(void) 2 3 struct cdev *p=kmalloc(sizeof(struct cdev),GFP_KERNEL); /*分配cdev的内存*/ 4 if (p) 5 memset(p, 0, sizeof(struct cdev); 6 p-kobj.ktype = &ktype_cdev_dynamic; 7 INIT_LIST_HEAD(&p-list); 8 kobject_init(&p-kobj); 9 10 return p; 11 cdev_add()函数和 cdev_del()函数分别向系统添加和删除一个cdev,完成字符设备的注册和注销。对 cdev_add()的调用通常发生在字符设备驱动模块加载函数中,而对cdev_del()函数的调用则通常发生在字符设备驱动模块卸载函数中。2) 分配和释放设备号在 调用 cdev_add() 函 数 向系统注册 字符 设备 之前 , 应首先调用register_chrdev_region()或 alloc_chrdev_region()函数向系统申请设备号。register_chrdev_region() 函 数 用 于 已 知 起 始 设 备的 设备 号 的 情 况; 而alloc_chrdev_region()用于设备号未知,向系统动态申请未被占用的设备号的情况,相反地 ,在 调用 cdev_del() 函 数 从系 统 注销 字符设备 之 后,unregister_chrdev_region()应该被调用以释放原先申请的设备号。3)file_operations结构体1 struct file_operations 2 3 struct module *owner; / 拥有该结构的模块的指针,一般为THIS_MODULES 5 loff_t(*llseek)(struct file *, loff_t, int); / 用来修改文件当前的读写位置 7 ssize_t(*read)(struct file *, char _ _user *, size_t, loff_t*); / 从设备中同步读取数据 9 ssize_t(*aio_read)(struct kiocb *, char _ _user *, size_t, loff_t); / 初始化一个异步的读取操作11 ssize_t(*write)(struct file *, const char _ _user *, size_t, loff_t*); / 向设备发送数据 13 ssize_t(*aio_write)(struct kiocb *, const char _ _user *, size_t, loff_t); / 初始化一个异步的写入操作 15 int(*readdir)(struct file *, void *, filldir_t); / 仅用于读取目录,对于设备文件,该字段为 NULL 17 unsigned int(*poll)(struct file *, struct poll_table_struct*); / 轮询函数,判断目前是否可以进行非阻塞的读取或写入 19 int(*ioctl)(struct inode *, struct file *, unsigned int, unsigned long); / 执行设备I/O控制命令 21 long(*unlocked_ioctl)(struct file *, unsigned int, unsigned long); / 不使用BLK文件系统,将使用此种函数指针代替ioctl 23 long(*compat_ioctl)(struct file *, unsigned int, unsigned long); / 在64位系统上,32位的ioctl调用将使用此函数指针代替 25 int(*mmap)(struct file *, struct vm_area_struct*); / 用于请求将设备内存映射到进程地址空间 27 int(*open)(struct inode *, struct file*); / 打开 29 int(*flush)(struct file*); 30 int(*release)(struct inode *, struct file*); / 关闭 32 int(*synch)(struct file *, struct dentry *, int datasync); / 刷新待处理的数据 34 int(*aio_fsync)(struct kiocb *, int datasync); / 异步fsync 36 int(*fasync)(int, struct file *, int); / 通知设备FASYNC标志发生变化 38 int(*lock)(struct file *, int, struct file_lock*); 39 ssize_t(*readv)(struct file *, const struct iovec *, unsigned long, loff_t*); 40 ssize_t(*writev)(struct file *, const struct iovec *, unsigned long, loff_t*); / readv和writev:分散/聚集型的读写操作 42 ssize_t(*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void*); / 通常为NULL 44 ssize_t(*sendpage)(struct file *, struct page *, int, size_t, loff_t *, int); / 通常为NULL 46 unsigned long(*get_unmapped_area)(struct file *,unsigned long, unsigned long, unsigned long, unsigned long); / 在进程地址空间找到一个将底层设备中的内存段映射的位置 49 int(*check_flags)(int); / 允许模块检查传递给fcntl(F_SETEL.)调用的标志 51 int(*dir_notify)(struct file *filp, unsigned long arg); / 仅对文件系统有效,驱动程序不必实现 53 int(*flock)(struct file *, int, struct file_lock*); 54 ;llseek()函数用来修改一个文件的当前读写位置,并将新位置返回,在出错时,这个函数返回一个负值read()函数用来从设备中读取数据,成功时函数返回读取的字节数,出错时返回一个负值。write()函数向设备发送数据,成功时该函数返回写入的字节数。如果此函数未被实现,当用户进行write()系统调用时,将得到-EINVAL返回值。readdir()函数仅用于目录,设备节点不需要实现它。 ioctl()提供设备相关控制命令的实现 (既不是读操作也不是写操作) , 当调用成功时,返回给调用程序一个非负值。内核本身识别部分控制命令,而不必调用设备驱动中的ioctl()。如果设备不提供ioctl()函数,对于内核不能识别的命令,用户进行ioctl()系统调用时将获得-EINVAL返回值。 mmap()函数将设备内存映射到进程内存中,如果设备驱动未实现此函数,用户进行 mmap()系统调用时将获得-ENODEV返回值。 这个函数对于帧缓冲等设备特别有意义。3)字符设备驱动的组成A、字符设备驱动模块加载与卸载函数字符设备驱动模块加载函数中应该实现设备号的申请和cdev的注册, 而在卸载函数中应实现设备号的释放和 cdev的注销常见的设备结构体、模块加载和卸载函数形式如代码清单:1/设备结构体 2 struct xxx_dev_t 3 4 struct cdev cdev; 5 . 6 xxx_dev; 7 /设备驱动模块加载函数 8 static int _ _init xxx_init(void) 9 10 . 11 cdev_init(&xxx_dev.cdev, &xxx_fops); /初始化cdev 12 xxx_dev.cdev.owner = THIS_MODULE; /获取字符设备号 14 if (xxx_major) 15 16 register_chrdev_region(xxx_dev_no, 1, DEV_NAME);17 18 else 19 20 alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME); 21 22 23 ret = cdev_add(&xxx_dev.cdev, xxx_dev_no, 1); /注册设备 24 . 25 26 /设备驱动模块卸载函数 27 static void _ _exit xxx_exit(void) 28 29 unregister_chrdev_region(xxx_dev_no, 1); /释放占用的设备号 30 cdev_del(&xxx_dev.cdev); /注销设备 31 . 32 B、字符设备驱动的file_operations 结构体中成员函数file_operations 结构体中成员函数是字符设备驱动与内核的接口,是用户空间对Linux进行系统调用最终的落实者。 大多数字符设备驱动会实现read()、 write()和 ioctl()函数,常见的字符设备驱动的这3个函数的形式如代码清单1 /* 读设备*/ 2 ssize_t xxx_read(struct file *filp, char _ _user *buf, size_t count, loff_t*f_pos) 4 5 . 6 copy_to_user(buf, ., .); 7 . 8 设备驱动的读函数中,filp是文件结构体指针,buf是用户空间内存的地址,该地址在内核空间不能直接读写,count是要读的字节数,f_pos是读的位置相对于文件开头的偏移。9 /* 写设备*/ 10 ssize_t xxx_write(struct file *filp, const char _ _user *buf, size_t count, loff_t *f_pos) 12 13 . 14 copy_from_user(., buf, .); 15 . 16 设备驱动的写函数中,filp是文件结构体指针
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 广东管理学原理中级自考试题及答案
- 了解中医考试题及答案
- 广东法律自考试题及答案
- 控制原理考试题及答案
- 客舱清洁考试题及答案
- 铝电解综合工主管竞选考核试卷及答案
- 带式球团焙烧工入职考核试卷及答案
- 中药合剂工专项考核试卷及答案
- 押题宝典教师招聘之《小学教师招聘》通关考试题库1套附答案详解
- 钽钠还原火法冶炼工理论知识考核试卷及答案
- 场景速写课件讲解
- 2025广东惠州惠城区招聘社区工作站工作人员66人笔试备考题库及答案解析
- (2025秋新版)教科版三年级上册科学全册教案
- 2025年新西师大版数学三年级上册全册课件
- 食品安全总监、食品安全员考核考试测试题及答案
- 第8课 西溪湿地教学设计-2025-2026学年小学地方、校本课程浙教版(2021)人·自然·社会
- 江淮十校2026届高三第一次联考物理试卷(含答案解析)
- 网络货运行业知识培训课件
- 人体十二经络系统解析
- 1.8《天气的影响》教学设计-教科版三上科学(新教材)
- 消防系统信号传输方案
评论
0/150
提交评论