Android-驱动学习-入门
基础概念:
设备号 : 分为主设备号和次设备号。设备号是16bit, 高8bit为主设备号,低8bit为次设备号。当我们创建一个设备节点时需要指定主设备号和次设备号。应用程序通过名称访问设备,而设备号指定了对应的驱动程序和对应的设备。主设备号标识设备对应的驱动程序,次设备号由内核使用,用于确定设备节点所指设备。你可以通过/proc/devices文件来查看系统设备的主设备号。
设备节点: Linux中设备节点是通过“mknod”命令来创建的。一个设备节点其实就是一个文件,Linux中称为设备文件。一般都创建在dev/目录下。
在userspace中可以打开设备节点,并通过驱动向设备节点写入数据。具体怎么实现呢?
1.kernel层的实现
a) 找到一个设备号devno,可以动态申请,也可以静态设定,假设静态设定为major,minor,通过宏MKDEV(major,minor)来生成devno
b) 构建对设备的操作函数集file_opreation结构体,里面包含了的设备的操作:open、read、write、release、ioctl等
c) 构建cdev结构体,里面填充两个主要成员dev(设备号)、file_operation(对设备的操作)
d) 把cdev添加到cdev链表中:cdev_init、cdev_add
具体代码:
首先, 内核在初始化的时候会调用initcall.init中保存的一份函数指针,并在初始化完成之后释放整个init区段。
当需要把函数xxx_init放到initcall.init区段的函数指针表中时,只需要声明: core_initcall(xxx_init);即可。
module_exit(xxx_exit)和前面的过程相似,在退出的时候会执行所有放在exit表中的函数。
所以一个驱动,最先执行的代码就是放在init列表里面的xxx_init函数。
我们看看这个函数做了什么:
static int __init xxx_init(void){dev_t dev;struct xxx_dev xxxdriver = kzalloc(sizeof(struct xxx_dev) + 5, GFP_KERNEL); // 先定义一个driver// 给driver中的变量赋值xlogdriver->buf = kzalloc(XLOGBUF_SIZE, GFP_KERNEL);xlogdriver->num = 1;xlogdriver->name = "xxx";xlogdriver->free_size = XLOGBUF_SIZE;alloc_chrdev_region(&dev, xlogdriver->minor_start, xlogdriver->num, xlogdriver->name);xlogdriver->cdev = cdev_alloc();ret = xxx_setup_cdev(dev); // 然后调用setup函数!!!
}
// 构建对设备的操作函数集file_opreation结构体
static const struct file_operations xxxfops = {
.owner = THIS_MODULE,
.read = xxx_read,
.write = xxx_write,
.poll = xxx_poll,
.open = xxx_open,
.release = xxx_close
};
static int xxx_setup_cdev(dev_t devno){cdev_init(xxxdriver->cdev, &xxxfops); // 初始化cdevxxxdriver->cdev->owner = THIS_MODULE;xxxdriver->cdev->ops = &xxxfops; // cdev的主要成员,对设备节点的操作err = cdev_add(xxxdriver->cdev, devno, 1); // 把cdev添加到cdev链表中xxxdriver->xxx_class = class_create(THIS_MODULE, "xxx");xlogdriver->xlog_dev = device_create(xlogdriver->xxx_class,NULL, devno, (void *)xlogdriver, "xlog");return 0;
}
然后重点实现的函数就是file_operations xxxfops中构建的函数xxx_read、xxx_write、xxx_poll、xxx_open和xxx_close。
实现完成之后userspace就可以通过这些函数去对xxx这个设备节点进行操作了。
eg:static ssize_t xxx_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos){int err = 0;size_t copy_bytes;u64 temp = count;mutex_lock(&xxxdriver->xxx_mutex); // 写入之前先上锁if (xxxBUF_SIZE < xxxdriver->writeindex + count) {copy_bytes = xxxBUF_SIZE - xxxdriver->writeindex;err = copy_from_user(xxxdriver->buf + xxxdriver->writeindex, buf, copy_bytes); // 从userspace的buf中读取数据写入xxxdriver->buferr = copy_from_user(xxxdriver->buf, buf + copy_bytes, count - copy_bytes);xxxdriver->writeindex = count - copy_bytes;} else {err = copy_from_user(xxxdriver->buf + xxxdriver->writeindex, buf, count);xxxdriver->writeindex += count;}xxxdriver->free_size -= count; // 更新剩余空间mutex_unlock(&xxxdriver->xxx_mutex); // 写完之后解锁wake_up_interruptible(&xxxdriver->wait_q);return count;
}
2. userspace的操作
int fd=open("/dev/xxx",O_RDWR)来打开设备文件,此设备对应有一个设备号,这是我们识别驱动和设备的桥梁。
打开 /dev/xxx时,根据设备号,在cdev链表中找到cdev这个结构体,cdev里面包含了file_operation结构体,有设备的各种操作,打开时就调用里面的.open 函数。
具体代码:
例如此时app有一些数据需要写入设备节点:
void wirte_to_xxx(char* str){int fd = open("/dev/xxx",O_RDWR); // 先打开设备节点,此处最终调用的就是xxx_openwrite(fd, str, strlen(str)); // 写入数据, 此处最终调用的就是xxx_writeclose(fd); // 写完之后关闭节点,此处最终调用的就是xxx_close
}
Android-驱动学习-入门相关推荐
- Android模拟器检测体系梳理,android驱动开发入门
安卓系统兼容性:目前模拟器上的Android系统仍然停留在4.x,部分达到5.1,使得部分对安卓版本有要求的应用或游戏在模拟器上运行体验不好. 底层关键技术 >>>> 虚拟化技 ...
- android studio 学习入门篇
开发第一应用 可以开发属于自己的应用,是否有点小激动?好吧!让我们开始,首先点击Start a new Android Studio Project创建工程: 接下来需要输入应用名称(第一个字母要大写 ...
- Android缓存学习入门
本文主要包括以下内容 利用LruCache实现内存缓存 利用DiskLruCache实现磁盘缓存 LruCache与DiskLruCache结合实例 利用了缓存机制的瀑布流实例 内存缓存的实现 pub ...
- 【安卓开发】android studio 学习入门篇
以下内容转载自:https://blog.csdn.net/myosotis5/article/details/79208707 (为防止链接失效,特备份文章内容,侵删) 开发第一应用 可以开发属于自 ...
- android驱动开发入门
Android 的硬件抽象层,简单来说,就是对Linux 内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节.也就是说,把 对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在 ...
- android驱动学习
android2.3 NV21 视频格式 android 2.3.4 T34H HDMI 移植 android2.2 . android2.3 sd卡挂载 androd2.3 音乐.录音.拍照时出问题 ...
- Android缓存学习入门(二)
本文主要包括以下内容 内存缓存策略 文件缓存策略 内存缓存策略 当有一个图片要去从网络下载的时候,我们并不会直接去从网络下载,因为在这个时代,用户的流量是宝贵的,耗流量的应用是不会得到用户的青睐的.那 ...
- Android驱动学习-内部机制_回顾binder框架关键点
内部机制_回顾binder框架关键点 server注册服务时, 对每个服务都提供不同的ptr/cookie, 在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie c ...
- Linux驱动学习——入门
模块化编程 编译加载查看命令 make 编译 lsmod 显示模块 insmod/rmmod 安装/卸载模块 dmesg打印log信息 dmesg -c 清除当前的log 试验环境 ubuntu 虚拟 ...
- Android驱动入门系列(一)
Android驱动入门系列(一) -- Android驱动简介及编写第一个Android驱动 以下文章参考网上搜到的<Android驱动开发全过程(有图有真相)>一文,其中根据自己的实 ...
最新文章
- Machine Learning Algorithm
- [A Dangerous Maze LightOJ - 1027 ][概率题]
- CSDN markdown中实现首行缩进(空格)的两种方法(“ ”)
- C语言经典算法100例-022-乒乓球比赛名单问题
- Nginx中gzip_static使用测试
- python开发工具下所有软件都打不开_Python 开发工具链全解
- rust风化速度_反驳《Golang、Rust的执行速度的对照,让人大吃一惊。》——不会别瞎说...
- 表情包+外卖+壁纸小程序源码
- 松下年净利润预计降20% 或启动新一轮裁员
- android高通camera驱动调试,高通Camera模块驱动指南资料
- java打印日历至Excel_如何利用Excel打印漂亮的工作日历
- 数据库插入数据时报错(使用sqlyog创建数据库表插入中文数据时报错Incorrect string value: ‘\xE4\xBB\x8E\xE5\x85\xA5…’ for column ‘)
- CF407C Curious Array
- 世界第 3 的滴滴裁员,求职必知独角兽公司排行榜
- OpenCvSharp 棋盘格标定助手
- java 锁 面试题_Java面试题-Java中的锁
- java解析网页全过程_Web页面的解析过程
- 【百科】CLEO 逐推縮寫命名法
- 动态创建js标签 script标签详细版
- 非人学园服务器维护,非人学园进不去怎么办 非人学园闪退黑屏怎么办