news 2026/1/29 8:49:55

AIDL Hal 开发笔记4----驱动开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AIDL Hal 开发笔记4----驱动开发

目录

  • 一、编写Linux 内核驱动
    • 1.1 编写驱动
    • 1.2 将模块编译进内核
  • 二、Native 程序测试驱动程序
  • 三、权限配置

驱动开发

一、编写Linux 内核驱动

1.1 编写驱动

Linux 驱动实际就是一个 Linux 内核模块。

首先,我们需要理解什么是内核模块?简单来说,内核模块是一段 “固定格式” 的代码,像一个“插件”一样,linux 内核可以动态的加载并执行这段代码,也可以把这段代码编译进内核,在内核启动的时候来执行这段代码。

下面我们写一个简单的 linux 驱动:在内核的drivers/char目录中添加 hello_driver.c

#include<linux/module.h>#include<linux/fs.h>#include<linux/errno.h>#include<linux/miscdevice.h>#include<linux/kernel.h>#include<linux/major.h>#include<linux/mutex.h>#include<linux/proc_fs.h>#include<linux/seq_file.h>#include<linux/stat.h>#include<linux/init.h>#include<linux/device.h>#include<linux/tty.h>#include<linux/kmod.h>#include<linux/gfp.h>/* 1. 确定主设备号 */staticintmajor=0;staticcharkernel_buf[1024];staticstructclass*hello_class;#defineMIN(a,b)(a<b?a:b)/* 3. 实现对应的open/read/write等函数,填入file_operations结构体 */staticssize_thello_drv_read(structfile*file,char__user*buf,size_tsize,loff_t*offset){interr;printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);err=copy_to_user(buf,kernel_buf,MIN(1024,size));returnMIN(1024,size);}staticssize_thello_drv_write(structfile*file,constchar__user*buf,size_tsize,loff_t*offset){interr;printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);err=copy_from_user(kernel_buf,buf,MIN(1024,size));returnMIN(1024,size);}staticinthello_drv_open(structinode*node,structfile*file){printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);return0;}staticinthello_drv_close(structinode*node,structfile*file){printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);return0;}/* 2. 定义自己的file_operations结构体 */staticstructfile_operationshello_drv={.owner=THIS_MODULE,.open=hello_drv_open,.read=hello_drv_read,.write=hello_drv_write,.release=hello_drv_close,};/* 4. 把file_operations结构体告诉内核:注册驱动程序 *//* 5. 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数 */staticint__inithello_init(void){interr;printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);major=register_chrdev(0,"hello",&hello_drv);/* /dev/hello *///提供设备信息,自动创建设备节点。// /dev/hellohello_class=class_create(THIS_MODULE,"hello_class");err=PTR_ERR(hello_class);if(IS_ERR(hello_class)){printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);unregister_chrdev(major,"hello");return-1;}device_create(hello_class,NULL,MKDEV(major,0),NULL,"hello");/* /dev/hello *///到这里我们就可以通过 /dev/hello 文件来访问我们的驱动程序了。return0;}/* 6. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数 */staticvoid__exithello_exit(void){printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);device_destroy(hello_class,MKDEV(major,0));class_destroy(hello_class);unregister_chrdev(major,"hello");}/* 7. 其他完善:提供设备信息,自动创建设备节点 */module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");

1.2 将模块编译进内核

接下来我们修改 /drivers/char/Kconfig 文件,使得我们的 hello_driver 模块,能出现在内核的编译选项中。

在 /drivers/char 中的 Kconfig 文件中添加:

config HELLO_DRIVER_MODULE bool"hello driver module support"defaulty

然后在 /drivers/char 下的 Makefile 文件中添加:

obj-$(CONFIG_HELLO_DRIVER_MODULE)+=hello_driver.o

当在 make menuconfig 编译菜单中选中了 hello module support,CONFIG_HELLO_MODULE的值是 y,没有选中值是 m(我们定义的默认值是 y):

  • obj-y += hello_driver.o 的意思是将 hello_driver.o 编译进内核
  • obj-m += hello_driver.o 的意思是文件 hello_driver.o 作为"模块"进行编译,不会编译到内核,但是会生成一个独立的 “hello_driver.ko” 文件,可以使用insmod命令将模块加载到内核中

最后配置内核:

kernel/linux-5.4$ make menuconfig

进入 Device Drivers 选项:

进入 Character devices


这里就可以看见我们刚才添加的选项,默认是选上的。

然后执行编译:

source build/envsetup.sh lunch xxx make

烧录后抓取 kernel日志

#dmesg用于显示开机信息adb shell dmesg|grep hello

二、Native 程序测试驱动程序

在 frameworks/base/native/ 目录下创建如下的目录结构:

hello_drv_test/├── Android.mk └── hello_drv_test.c

其中 hello_drv_test.c 的内容如下:

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<stdio.h>#include<string.h>/* * ./hello_drv_test -w abc * ./hello_drv_test -r */intmain(intargc,char**argv){intfd;charbuf[1024];intlen;/* 1. 判断参数 */if(argc<2){printf("Usage: %s -w <string>\n",argv[0]);printf(" %s -r\n",argv[0]);return-1;}/* 2. 打开文件 */fd=open("/dev/hello",O_RDWR);if(fd==-1){printf("can not open file /dev/hello\n");return-1;}/* 3. 写文件或读文件 */if((0==strcmp(argv[1],"-w"))&&(argc==3)){len=strlen(argv[2])+1;len=len<1024?len:1024;write(fd,argv[2],len);}else{len=read(fd,buf,1024);buf[1023]='\0';printf("APP read : %s\n",buf);}close(fd);return0;}

测试程序的内容很简单,就是根据命令行参数读写 /dev/hello文件。

接着编写 Android.mk 文件:

LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS:=optional LOCAL_SRC_FILES:=\ hello_drv_test.c LOCAL_MODULE:=hello_drv_test include $(BUILD_EXECUTABLE)

编译程序并push到机器:

# 编译 cd frameworks/base/native/hello_drv_test mm cd-adb push out/target/product/ceres-b7/system/bin/hello_drv_testsystem/bin/hello_drv_test system/bin adb shell # 执行程序 cd system/bin./hello_drv_test-w"hello"./hello_drv_test-r

执行程序的结果如下所示:


三、权限配置

要把驱动集成到系统中,还需要添加一些权限相关的配置:

system/core/rootdir/ueventd.rc中添加:

/dev/hello0666root root

system/sepolicy/device.te中添加:

typehello_dev_t,dev_type;

system/sepolicy/file_contexts中添加

/dev/hello u:object_r:hello_dev_t:s0

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/22 1:35:34

AI赋能的11项论文写作解决方案,涵盖LaTeX排版与智能改写功能

工具对比排名 工具名称 核心优势 支持LaTeX 适用场景 aibiye AIGC率降个位数&#xff0c;兼容知网规则 是 AI痕迹强处理 aicheck 学术改写优化&#xff0c;语义保留佳 是 格式统一化 askpaper 降重降AI一体&#xff0c;20分钟快速响应 是 初稿优化 秒篇 人类特…

作者头像 李华
网站建设 2026/1/23 8:33:17

导师严选2026自考AI论文网站TOP10:高效写作全维度测评

导师严选2026自考AI论文网站TOP10&#xff1a;高效写作全维度测评 2026年自考AI论文写作工具测评&#xff1a;精准定位高效写作新标杆 随着人工智能技术的不断进步&#xff0c;越来越多的自考生开始依赖AI写作工具来提升论文撰写效率。然而&#xff0c;市面上的平台种类繁多&am…

作者头像 李华
网站建设 2026/1/22 6:46:02

收藏级指南:Agentic RAG 彻底升级传统RAG,打造能干活的AI数字同事

Agentic RAG作为传统RAG的颠覆性升级方案&#xff0c;核心是将静态的“检索-生成”流程&#xff0c;重构为智能体驱动的动态自适应工作流。传统RAG仅能完成单次问答的闭环&#xff0c;而Agentic RAG凭借推理规划、工具调用、自我修正的核心能力&#xff0c;可承接复杂任务落地。…

作者头像 李华
网站建设 2026/1/25 7:18:48

【计算化学与人工智能驱动的 MOFs 性能预测与筛选技术】

MOFs 性能预测与筛选技术概述 金属有机框架&#xff08;MOFs&#xff09;因其高孔隙率和可调性在气体存储、分离等领域具有广泛应用。计算化学与人工智能&#xff08;AI&#xff09;的结合显著加速了MOFs的性能预测与筛选流程&#xff0c;通过数据驱动方法降低实验成本并提高效…

作者头像 李华
网站建设 2026/1/28 20:43:25

listmap数据变驼峰

/*** listmap数据_变驼峰** param list* return*/public static List<Map<String, Object>> convertListToCamelCase(List<Map<String, Object>> list) {List<Map<String, Object>> data new ArrayList<>();if (null list || list…

作者头像 李华
网站建设 2026/1/21 23:00:50

【Java毕设全套源码+文档】基于springboot的可追溯果蔬生产过程的管理系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华