自己动手写驱动程序
来源:互联网 发布:linux https 编辑:程序博客网 时间:2024/05/28 15:36
一、编码思维导图
二、编写代码
memdev.c
三、函数学习
设备初始化:cdev_init
原型:void cdev_init(struct cdev *cdev, const struct file_operations *fops);
cdev:待初始化的cdev结构
fops:设备对应的操作函数集
动态分配设备号:alloc_chrdev_region
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
dev:分配后设备号的地址
baseminor:起始地设备序号
count:分配的个数
name:分配后的设备别名
设备注册:cdev_add
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
p:待添加的字符设备结构
dev:设备号
count:该类设备的设备个数
注销设备:cdev_del
void cdev_del(struct cdev *p);
p:待注销的设备结构
释放设备号:unregister_chrdev_region
void unregister_chrdev_region(dev_t from, unsigned count);
from:待释放设备号
count:释放的设备个数
四、驱动访问模型
1.应用程序访问read
arm-linux-objdump -d read_mem
>>libc_read:
将3放入r7寄存器中
调用svc,进入内核空间
通过查表找到read并使用
在entry-common.S中
利用3这个编号找到sys_read
>>>read_write.c
二、编写代码
memdev.c
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- #include <asm/uaccess.h>
- struct cdev mdev; //1.静态分配cdev
- dev_t devno;
- int dev1_regs[5];
- int dev2_regs[5];
- loff_t mem_lseek(struct file *filep, loff_t offset, int whence)
- {
- loff_t new_pos = 0;
- switch(whence) {
- case SEEK_SET:
- new_pos = 0 + offset;
- break;
- case SEEK_CUR:
- new_pos = filep->f_pos + offset;
- break;
- case SEEK_END:
- new_pos = 5*sizeof(int) + offset;
- break;
- default:
- break;
- }
- filep->f_pos = new_pos;
- return new_pos;
- }
- size_t mem_read(struct file *filep, char __user *buf, size_t size, loff_t *ppos)
- {
- int *reg_base = filep->private_data;
- copy_to_user(buf, reg_base+(*ppos), size);
- filep->f_pos += size;
- return size;
- }
- size_t mem_write(struct file *filep, const char __user *buf, size_t size, loff_t *ppos)
- {
- int *reg_base = filep->private_data;
- copy_from_user(reg_base+(*ppos), buf, size);
- filep->f_pos += size;
- return size;
- }
- size_t mem_open(struct inode *node, struct file *filep)
- {
- int num = MINOR(node->i_rdev);
- if(num == 0)
- filep->private_data = dev1_regs;
- else if(num == 1)
- filep->private_data = dev2_regs;
- return 0;
- }
- int mem_close (struct inode *node, struct file *filep)
- {
- return 0;
- }
- struct file_operations memfops =
- {
- .llseek = mem_lseek,
- .open = mem_open,
- .write = mem_write,
- .read = mem_read,
- .release = mem_close,
- };
- int memdev_init()
- {
- cdev_init(&mdev, &memfops); //2.初始化cdev
- alloc_chrdev_region(&devno, 0, 2, "memdev"); //3.动态分配设备号到devno
- cdev_add(&mdev, devno, 2); //4.注册cdev
- return 0;
- }
- void memdev_exit()
- {
- cdev_del(&mdev); //5.设备注销
- unregister_chrdev_region(devno, 2); //6.设备号注销
- }
- module_init(memdev_init); //初始化入口
- module_exit(memdev_exit); //模块退出
三、函数学习
设备初始化:cdev_init
原型:void cdev_init(struct cdev *cdev, const struct file_operations *fops);
cdev:待初始化的cdev结构
fops:设备对应的操作函数集
动态分配设备号:alloc_chrdev_region
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
dev:分配后设备号的地址
baseminor:起始地设备序号
count:分配的个数
name:分配后的设备别名
设备注册:cdev_add
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
p:待添加的字符设备结构
dev:设备号
count:该类设备的设备个数
注销设备:cdev_del
void cdev_del(struct cdev *p);
p:待注销的设备结构
释放设备号:unregister_chrdev_region
void unregister_chrdev_region(dev_t from, unsigned count);
from:待释放设备号
count:释放的设备个数
四、驱动访问模型
1.应用程序访问read
arm-linux-objdump -d read_mem
- 00008228 <main>:
- 8228: e92d4800 push {fp, lr}
- 822c: e28db004 add fp, sp, #4 ; 0x4
- 8230: e24dd008 sub sp, sp, #8 ; 0x8
- 8234: e3a03000 mov r3, #0 ; 0x0
- 8238: e50b3008 str r3, [fp, #-8]
- 823c: e3a03000 mov r3, #0 ; 0x0
- 8240: e50b300c str r3, [fp, #-12]
- 8244: e59f0044 ldr r0, [pc, #68] ; 8290 <main+0x68>
- 8248: e3a01002 mov r1, #2 ; 0x2
- 824c: eb0028a3 bl 124e0 <__libc_open>
- 8250: e1a03000 mov r3, r0
- 8254: e50b3008 str r3, [fp, #-8]
- 8258: e24b300c sub r3, fp, #12 ; 0xc
- 825c: e51b0008 ldr r0, [fp, #-8]
- 8260: e1a01003 mov r1, r3
- 8264: e3a02004 mov r2, #4 ; 0x4
- 8268: eb0028c0 bl 12570 <__libc_read>
- 00012570 <__libc_read>:
- 12570: e51fc028 ldr ip, [pc, #-40] ; 12550 <__libc_open+0x70>
- 12574: e79fc00c ldr ip, [pc, ip]
- 12578: e33c0000 teq ip, #0 ; 0x0
- 1257c: 1a000006 bne 1259c <__libc_read+0x2c>
- 12580: e1a0c007 mov ip, r7
- 12584: e3a07003 mov r7, #3 ; 0x3
- 12588: ef000000 svc 0x00000000
调用svc,进入内核空间
通过查表找到read并使用
在entry-common.S中
- ENTRY(sys_call_table)
- #include "calls.S"
- #undef ABI
- #undef OBSOLETE
- /*============================================================================
- * Special system call wrappers
- */
- @ r0 = syscall number
- @ r8 = syscall table
- sys_syscall:
- bic scno, r0, #__NR_OABI_SYSCALL_BASE
- cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
- cmpne scno, #NR_syscalls @ check range
- stmloia sp, {r5, r6} @ shuffle args
- movlo r0, r1
- movlo r1, r2
- movlo r2, r3
- movlo r3, r4
- ldrlo pc, [tbl, scno, lsl #2]
- b sys_ni_syscall
- ENDPROC(sys_syscall)
>>>read_write.c
- ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
- {
- ssize_t ret;
- if (!(file->f_mode & FMODE_READ))
- return -EBADF;
- if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
- return -EINVAL;
- if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
- return -EFAULT;
- ret = rw_verify_area(READ, file, pos, count);
- if (ret >= 0) {
- count = ret;
- if (file->f_op->read)
- ret = file->f_op->read(file, buf, count, pos); //这里调用了file_operations的read
- else
- ret = do_sync_read(file, buf, count, pos);
- if (ret > 0) {
- fsnotify_access(file->f_path.dentry);
- add_rchar(current, ret);
- }
- inc_syscr(current);
- }
- return ret;
- }
0
上一篇:字符设备驱动模型
下一篇:LED驱动程序设计
相关热门文章
- SHTML是什么_SSI有什么用...
- 查看linux中某个端口(port)...
- 卡尔曼滤波的原理说明...
- shell中字符串操作
- 关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议
阅读全文
0 0
- 自己动手写驱动程序
- 自己动手写操作系统
- [转载]自己动手写操作系统
- 自己动手写操作系统(一)
- 自己动手写操作系统(二)
- 自己动手写操作系统(一)
- 《自己动手写操作系统》读书笔记
- 自己动手写操作系统(一)
- 自己动手写操作系统(二)
- 读《自己动手写操作系统》
- 自己动手写操作系统
- 自己动手写进程管理器
- 《自己动手写操作系统》观感
- 自己动手写操作系统
- 自己动手写数据库连接池
- 读《自己动手写操作系统》
- 自己动手写操作系统
- 自己动手写javascript日历
- Linux内核链表
- 游标(经常使用)
- Linux驱动开发前奏
- 字符设备驱动模型
- Android源码编译
- 自己动手写驱动程序
- SQL 注入防御方法总结
- LED驱动程序设计
- 以太坊GAS相关知识
- 按键驱动程序设计
- 中断分层和按键去抖
- 阻塞型驱动设计
- 总线设备驱动模型和平台设备模型
- tty驱动程序架构
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
金府
金座
东方金座天地
深圳嘉葆润金座
南京金轮星光名座
嘉葆润金座租房
西湖金座酒店
天长金座
金庭
金康
神农金康
金康药房
金康过桥米线
金庸群侠传x
金庸群侠x
金庸群侠传
金庸作品
金庸全集
金庸群侠
金庸网
仙武金庸
金庸群侠传3
金庸杭州
金庸徐志摩
金庸群侠传5
碧血剑 金庸
金庸吧
越女剑 金庸
连城诀 金庸
金庸名句
金庸作品集 金庸
金庸和古龙
金庸的作品
金庸简介
金庸新
金庸作品集
金庸的书
金庸新作品
金庸人物
金庸新 全集
免费金庸