基础概念:

设备号 : 分为主设备号和次设备号。设备号是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-驱动学习-入门相关推荐

  1. Android模拟器检测体系梳理,android驱动开发入门

    安卓系统兼容性:目前模拟器上的Android系统仍然停留在4.x,部分达到5.1,使得部分对安卓版本有要求的应用或游戏在模拟器上运行体验不好. 底层关键技术 >>>> 虚拟化技 ...

  2. android studio 学习入门篇

    开发第一应用 可以开发属于自己的应用,是否有点小激动?好吧!让我们开始,首先点击Start a new Android Studio Project创建工程: 接下来需要输入应用名称(第一个字母要大写 ...

  3. Android缓存学习入门

    本文主要包括以下内容 利用LruCache实现内存缓存 利用DiskLruCache实现磁盘缓存 LruCache与DiskLruCache结合实例 利用了缓存机制的瀑布流实例 内存缓存的实现 pub ...

  4. 【安卓开发】android studio 学习入门篇

    以下内容转载自:https://blog.csdn.net/myosotis5/article/details/79208707 (为防止链接失效,特备份文章内容,侵删) 开发第一应用 可以开发属于自 ...

  5. android驱动开发入门

    Android 的硬件抽象层,简单来说,就是对Linux 内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节.也就是说,把 对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在 ...

  6. android驱动学习

    android2.3 NV21 视频格式 android 2.3.4 T34H HDMI 移植 android2.2 . android2.3 sd卡挂载 androd2.3 音乐.录音.拍照时出问题 ...

  7. Android缓存学习入门(二)

    本文主要包括以下内容 内存缓存策略 文件缓存策略 内存缓存策略 当有一个图片要去从网络下载的时候,我们并不会直接去从网络下载,因为在这个时代,用户的流量是宝贵的,耗流量的应用是不会得到用户的青睐的.那 ...

  8. Android驱动学习-内部机制_回顾binder框架关键点

    内部机制_回顾binder框架关键点 server注册服务时, 对每个服务都提供不同的ptr/cookie, 在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie c ...

  9. Linux驱动学习——入门

    模块化编程 编译加载查看命令 make 编译 lsmod 显示模块 insmod/rmmod 安装/卸载模块 dmesg打印log信息 dmesg -c 清除当前的log 试验环境 ubuntu 虚拟 ...

  10. Android驱动入门系列(一)

    Android驱动入门系列(一)   -- Android驱动简介及编写第一个Android驱动 以下文章参考网上搜到的<Android驱动开发全过程(有图有真相)>一文,其中根据自己的实 ...

最新文章

  1. Machine Learning Algorithm
  2. [A Dangerous Maze LightOJ - 1027 ][概率题]
  3. CSDN markdown中实现首行缩进(空格)的两种方法(“  ”)
  4. C语言经典算法100例-022-乒乓球比赛名单问题
  5. Nginx中gzip_static使用测试
  6. python开发工具下所有软件都打不开_Python 开发工具链全解
  7. rust风化速度_反驳《Golang、Rust的执行速度的对照,让人大吃一惊。》——不会别瞎说...
  8. 表情包+外卖+壁纸小程序源码
  9. 松下年净利润预计降20% 或启动新一轮裁员
  10. android高通camera驱动调试,高通Camera模块驱动指南资料
  11. java打印日历至Excel_如何利用Excel打印漂亮的工作日历
  12. 数据库插入数据时报错(使用sqlyog创建数据库表插入中文数据时报错Incorrect string value: ‘\xE4\xBB\x8E\xE5\x85\xA5…’ for column ‘)
  13. CF407C Curious Array
  14. 世界第 3 的滴滴裁员,求职必知独角兽公司排行榜
  15. OpenCvSharp 棋盘格标定助手
  16. java 锁 面试题_Java面试题-Java中的锁
  17. java解析网页全过程_Web页面的解析过程
  18. 【百科】CLEO 逐推縮寫命名法
  19. 动态创建js标签 script标签详细版
  20. 非人学园服务器维护,非人学园进不去怎么办 非人学园闪退黑屏怎么办

热门文章

  1. 类似百度的2012世界末日地震效果
  2. 208个最新最全大数据/人工智能专有名词术语 中英对照
  3. nmn美国下架,nmn对肝脏有副作用吗,有实验证明!
  4. CT三维重建基本后处理方法
  5. unity3d怎么让模型动起来_让对象在Unity3D中动起来
  6. 学区摇号软件设计_上名校摇号的套路你懂得多少?
  7. 反转(reverse)
  8. Ubuntu数据恢复总结
  9. echarts 地图密集迁移图
  10. wend计算机语言,1.12基本算法语言(第三课时)汇编.ppt