Android内核之Binder通信写操作:binder_thread_write用法实例(七十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2.Android内核之binder_thread_write介绍
    • 🌻3.代码实例
      • 🐓3.1 发送Binder消息
      • 🐓3.2 发送Binder事件通知
      • 🐓3.3 发送Binder异步消息

🌻1.前言

本篇目的:Android内核之Binder通信写操作:binder_thread_write用法实例

🌻2.Android内核之binder_thread_write介绍

  • binder_thread_write函数是Android内核中用于Binder线程通信的关键函数之一。Binder是Android系统中用于进程间通信(IPC)的机制,它通过驱动程序实现。在Binder机制中,每个进程都有一个专门的Binder线程,用于处理与其他进程的通信请求。

  • binder_thread_write函数主要负责向目标Binder线程发送消息。它接受参数包括目标线程的信息、要发送的数据、数据的大小等,并将这些信息封装成一个Binder交易数据结构,最终通过驱动程序发送给目标线程。

  • 该函数的关键步骤如下:

  1. 参数验证: 首先,函数会验证传入的参数,确保它们的有效性和合法性,包括目标线程的有效性、发送数据的大小等。

  2. 构造Binder交易数据: 接下来,函数会根据传入的参数构造一个Binder交易数据结构。这个数据结构包含了要发送的消息内容、目标线程的标识符等信息。

  3. 调用Binder驱动发送消息: 函数将构造好的Binder交易数据结构传递给Binder驱动程序,通过驱动程序实现消息的发送。Binder驱动会负责将消息传递给目标线程,并处理相关的错误情况。

  4. 返回结果: 最后,函数根据发送结果返回相应的错误码或成功状态,通知调用者发送消息的结果。

  • binder_thread_write函数的调用通常发生在Android系统的内核空间,例如系统服务或驱动程序中。它允许不同的进程之间进行通信,实现了Android系统中各个组件之间的协作与交互。作为Android系统中IPC机制的核心之一,Binder机制在实现高效稳定的进程通信方面发挥着重要作用,而binder_thread_write函数则是其中的关键环节之一。

🌻3.代码实例

🐓3.1 发送Binder消息

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/android/binder.h>#define DEVICE_NAME "binder_example"
#define BINDER_DEV_PATH "/dev/binder_example"static int major_number;
static struct class *binder_class = NULL;
static struct device *binder_device = NULL;// 打开Binder设备
static int binder_open(struct inode *inode, struct file *file) {printk(KERN_INFO "Binder device opened\n");return 0;
}// 释放Binder设备
static int binder_release(struct inode *inode, struct file *file) {printk(KERN_INFO "Binder device closed\n");return 0;
}// 实现Binder设备的write操作
static ssize_t binder_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) {struct binder_transaction_data *transaction_data;// 从用户空间拷贝数据到内核空间if (copy_from_user(&transaction_data, buffer, sizeof(struct binder_transaction_data)) != 0) {return -EFAULT;}// 使用binder_thread_write发送Binder消息binder_thread_write(transaction_data);return count;
}// 初始化Binder设备
static int __init binder_init(void) {// 分配主设备号major_number = register_chrdev(0, DEVICE_NAME, &binder_fops);if (major_number < 0) {printk(KERN_ALERT "Failed to register a major number\n");return major_number;}// 创建设备类binder_class = class_create(THIS_MODULE, DEVICE_NAME);if (IS_ERR(binder_class)) {unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_ALERT "Failed to register device class\n");return PTR_ERR(binder_class);}// 创建设备节点binder_device = device_create(binder_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);if (IS_ERR(binder_device)) {class_destroy(binder_class);unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_ALERT "Failed to create the device\n");return PTR_ERR(binder_device);}printk(KERN_INFO "Binder module initialized\n");return 0;
}// 卸载Binder设备
static void __exit binder_exit(void) {device_destroy(binder_class, MKDEV(major_number, 0));class_unregister(binder_class);class_destroy(binder_class);unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_INFO "Binder module exit\n");
}module_init(binder_init);
module_exit(binder_exit);
MODULE_LICENSE("GPL");

🐓3.2 发送Binder事件通知

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/android/binder.h>#define DEVICE_NAME "binder_example"
#define BINDER_DEV_PATH "/dev/binder_example"static int major_number;
static struct class *binder_class = NULL;
static struct device *binder_device = NULL;// 打开Binder设备
static int binder_open(struct inode *inode, struct file *file) {printk(KERN_INFO "Binder device opened\n");return 0;
}// 释放Binder设备
static int binder_release(struct inode *inode, struct file *file) {printk(KERN_INFO "Binder device closed\n");return 0;
}// 实现Binder设备的write操作
static ssize_t binder_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) {struct binder_event *event;// 从用户空间拷贝数据到内核空间if (copy_from_user(&event, buffer, sizeof(struct binder_event)) != 0) {return -EFAULT;}// 使用binder_thread_write发送Binder事件通知binder_thread_write(event);return count;
}// 初始化Binder设备
static int __init binder_init(void) {// 分配主设备号major_number = register_chrdev(0, DEVICE_NAME, &binder_fops);if (major_number < 0) {printk(KERN_ALERT "Failed to register a major number\n");return major_number;}// 创建设备类binder_class = class_create(THIS_MODULE, DEVICE_NAME);if (IS_ERR(binder_class)) {unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_ALERT "Failed to register device class\n");return PTR_ERR(binder_class);}// 创建设备节点binder_device = device_create(binder_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);if (IS_ERR(binder_device)) {class_destroy(binder_class);unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_ALERT "Failed to create the device\n");return PTR_ERR(binder_device);}printk(KERN_INFO "Binder module initialized\n");return 0;
}// 卸载Binder设备
static void __exit binder_exit(void) {device_destroy(binder_class, MKDEV(major_number, 0));class_unregister(binder_class);class_destroy(binder_class);unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_INFO "Binder module exit\n");
}module_init(binder_init);
module_exit(binder_exit);MODULE_LICENSE("GPL");

🐓3.3 发送Binder异步消息

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/android/binder.h>#define DEVICE_NAME "binder_example"
#define BINDER_DEV_PATH "/dev/binder_example"static int major_number;
static struct class *binder_class = NULL;
static struct device *binder_device = NULL;// 打开Binder设备
static int binder_open(struct inode *inode, struct file *file) {printk(KERN_INFO "Binder device opened\n");return 0;
}// 释放Binder设备
static int binder_release(struct inode *inode, struct file *file) {printk(KERN_INFO "Binder device closed\n");return 0;
}// 实现Binder设备的write操作
static ssize_t binder_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) {struct binder_thread *thread;// 从用户空间拷贝数据到内核空间if (copy_from_user(&thread, buffer, sizeof(struct binder_thread)) != 0) {return -EFAULT;}// 使用binder_thread_write发送Binder异步消息binder_thread_write(thread);return count;
}// 初始化Binder设备
static int __init binder_init(void) {// 分配主设备号major_number = register_chrdev(0, DEVICE_NAME, &binder_fops);if (major_number < 0) {printk(KERN_ALERT "Failed to register a major number\n");return major_number;}// 创建设备类binder_class = class_create(THIS_MODULE, DEVICE_NAME);if (IS_ERR(binder_class)) {unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_ALERT "Failed to register device class\n");return PTR_ERR(binder_class);}// 创建设备节点binder_device = device_create(binder_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);if (IS_ERR(binder_device)) {class_destroy(binder_class);unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_ALERT "Failed to create the device\n");return PTR_ERR(binder_device);}printk(KERN_INFO "Binder module initialized\n");return 0;
}// 卸载Binder设备
static void __exit binder_exit(void) {device_destroy(binder_class, MKDEV(major_number, 0));class_unregister(binder_class);class_destroy(binder_class);unregister_chrdev(major_number, DEVICE_NAME);printk(KERN_INFO "Binder module exit\n");
}module_init(binder_init);
module_exit(binder_exit);MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3019057.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

vue3+elementPlus:el-input输入框设置数字小数点

<el-input-numberplaceholder"请输入"v-model.number"scope.row.threeValue"class"mx-4":step"0.001" //精度controls-position"right" //幅度/></template> 上一篇文章&#xff0c; vue3echarts&#xff1a;e…

如何更好地使用Kafka? - 事先预防篇

要确保Kafka在使用过程中的稳定性&#xff0c;需要从kafka在业务中的使用周期进行依次保障。主要可以分为&#xff1a;事先预防&#xff08;通过规范的使用、开发&#xff0c;预防问题产生&#xff09;、运行时监控&#xff08;保障集群稳定&#xff0c;出问题能及时发现&#…

windows10打印机共享完美解决方案

提到文件共享大家并不陌生,相关的还有打印机共享,这个多见于单位、复印部,在一个区域网里多台电脑共用一台打印机,打印资料非常方便,就包括在家里,我们现在一般都会有多台电脑或设备,通过家庭网络联接,如果共享一台打印机的话也是件便捷的事。 但是随着操作系统的更新…

【IP:Internet Protocol,子网(Subnets),IPv6:动机,层次编址:路由聚集(rout aggregation)】

文章目录 IP&#xff1a;Internet Protocol互联网的的网络层IP分片和重组&#xff08;Fragmentation & Reassembly&#xff09;IP编址&#xff1a;引论子网&#xff08;Subnets&#xff09;特殊IP地址IP 编址: CIDR子网掩码&#xff08;Subnet mask&#xff09;转发表和转发…

Linux学习笔记:信号

信号 在Linux中什么是信号信号的产生方式硬件产生的信号软件产生的信号异常产生的信号 进程对信号的处理信号的保存信号方法更改函数signal信号处理的更改恢复默认信号忽略 信号的管理信号集 sigset_t对信号集的操作 信号的捕捉过程 在Linux中什么是信号 在 Linux 系统中&…

如何备考PMP才能一次通过?

PMP备考一个月就能通过&#xff0c;培训机构中就应该这么学&#xff01; PMP考试的难度其实并没有大家想象中的那么大&#xff0c;现在培训机构的通过率基本也在90%以上&#xff0c;而这90%以上也基本都是头一次参加考试很少有参加重考的学员。我就是在威班PMP培训了一个多月一…

JVS物联网平台5.7功能新增说明

项目介绍 JVS是企业级数字化服务构建的基础脚手架&#xff0c;主要解决企业信息化项目交付难、实施效率低、开发成本高的问题&#xff0c;采用微服务配置化的方式&#xff0c;提供了 低代码数据分析物联网的核心能力产品&#xff0c;并构建了协同办公、企业常用的管理工具等&am…

深度学习Day-16:实现天气预测

&#x1f368; 本文为&#xff1a;[&#x1f517;365天深度学习训练营] 中的学习记录博客 &#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制] 要求&#xff1a;根据提供的数据集对RainTomorrow进行预测 一、 基础配置 语言环境&#xff1a;Python3.7编译器选择…

yolov8任务之目标检测

对象检测 对象检测是一项涉及识别图像或视频流中对象的位置和类别的任务。对象检测器的输出是一组包围图像中对象的边界框&#xff0c;以及每个框的类标签和置信度分数。当您需要识别场景中感兴趣的对象&#xff0c;但不需要确切知道对象在哪里或其确切形状时&#xff0c;对象检…

短视频矩阵系统源码saas开发--可视化剪辑、矩阵托管、多功能合一开发

短视频矩阵系统源码saas开发&#xff08;可视化剪辑、矩阵托管、智能私信聚合、线索转化、数据看板、seo关键词、子账号等多个板块开发&#xff09; 短视频矩阵系统是一种集成了多种功能的系统&#xff0c;旨在帮助用户在短视频平台上进行高效的内容创作、管理和发布。根据您提…

3. 分布式链路追踪的链路日志设计

前言 分布式链路追踪的客户端实现中&#xff0c;我们会通过各种手段和规则得到一个又一个的Span&#xff0c;得到这些Span后&#xff0c;需要在分布式链路追踪的服务端这边汇总这些Span并拼接出一条请求链路&#xff0c;那么这里就存在一个问题&#xff0c;客户端得到的Span如…

Qt跨平台开发demo(适用萌新)

最近需要参与一款Qt跨平台的软件开发&#xff0c;在此之前&#xff0c;特把基础信息做学习和梳理&#xff0c;仅供参考。 所使用的技术和版本情况如下&#xff1a; 虚拟机&#xff1a;VMware 16.2.5操作系统&#xff1a;ubuntu-20.04.6-desktop-amd64&#xff1a;Mysql数据库…

机器人系统仿真

0、何为仿真 通过计算机对实体机器人系统进行模拟的技术。 1、为何仿真 低成本&#xff1a; 机器人实体一般价格昂贵&#xff0c;为降低机器人学习、调试的成本&#xff1b;高效&#xff1a; 搭建的环境更为多样且灵活&#xff0c;可以提高测试效率以及测试覆盖率&#xff1b…

MS86235运算放大器可Pin to Pin兼容OPA2835

MS8635/MS86235是一款低功耗的单/双通道低噪声、轨到轨输出、高速运算放大器&#xff0c;可由2.7V至5V范围内的单电源或者1.35V至2.5V范围内的双电源供电运行。可Pin to Pin兼容OPA2835。每通道仅消耗630μA的电流&#xff0c;单位增益带宽为66MHz&#xff0c;在节能模式下&…

从几个方面判断代理IP的质量?

代理IP的质量对于网络活动至关重要&#xff0c;它直接影响到用户的隐私保护、访问速度、稳定性以及整体的网络体验。以下是从几个关键方面来判断代理IP质量的详细分析&#xff1a; 第一点稳定性&#xff1a;稳定性是评估代理IP质量的首要因素。一个优质的代理IP应该具备高稳定…

LINUX 入门 8

LINUX 入门 8 day10 20240507 耗时&#xff1a;90min 有点到倦怠期了 课程链接地址 第8章 TCP服务器 1 TCP服务器的介绍 开始讲服务器端&#xff0c;之前是客户端DNShttps请求 基础&#xff1a;网络编程并发服务器&#xff1a;多客户端 一请求&#xff0c;一线程 veryold…

武汉星起航:亚马逊:跨境电商领军平台,中国卖家全球拓展的首选

2015年&#xff0c;亚马逊全球开店业务正式进入中国&#xff0c;为中国卖家带来了全新的跨境电商机遇。如今&#xff0c;亚马逊已在全球拥有包括美国、加拿大、墨西哥、英国、法国、德国等在内的17大海外站点&#xff0c;为中国卖家提供了广阔的销售市场。武汉星起航将详细探讨…

2024年北京服贸会媒体邀约资源有哪些?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 2024年北京服贸会&#xff08;中国国际服务贸易交易会&#xff0c;简称CIFTIS&#xff09;作为中国重要的国际性服务贸易盛会&#xff0c;会吸引众多媒体的关注和参与。媒体邀约资源通常…

Linux中每当执行‘mount’命令(或其他命令)时,自动激活执行脚本:输入密码,才可以执行mount

要实现这个功能&#xff0c;可以通过创建一个自定义的mount命令的包装器&#xff08;wrapper&#xff09;来完成。这个包装器脚本会首先提示用户输入密码&#xff0c;如果密码正确&#xff0c;则执行实际的mount命令。以下是创建这样一个包装器的步骤&#xff1a; 创建一个名为…

【强训笔记】day14

NO.1 思路&#xff1a;用一个哈希表&#xff0c;先遍历s1&#xff0c;统计哈希表内的字符个数&#xff0c;在遍历s2&#xff0c;s2中的字符在哈希表中减去&#xff0c;如果哈希表中的字符个数小于0那么就输出No。 代码实现&#xff1a; #include <iostream> #include&…