南通门户网站,手机网站首页布局设计,濮阳建设网,广东软文网站推广文案文心一言的回答
Binder驱动是Android操作系统中用于进程间通信#xff08;IPC#xff09;的机制。它提供了一种高效、跨进程的数据传输方式#xff0c;使得应用程序的不同组件可以在Android系统上互相通信。
Binder驱动基于Linux内核#xff0c;其核心组件是一个称为Bind…文心一言的回答
Binder驱动是Android操作系统中用于进程间通信IPC的机制。它提供了一种高效、跨进程的数据传输方式使得应用程序的不同组件可以在Android系统上互相通信。
Binder驱动基于Linux内核其核心组件是一个称为Binder IPC的通信协议。通过使用Binder IPC应用程序的不同组件可以共享数据、资源和功能从而实现更高效的应用程序运行。
Binder驱动的主要特点是高效、安全和灵活。它支持跨进程通信使得应用程序的不同组件可以协同工作从而提高了应用程序的效率和性能。同时Binder驱动还提供了一系列的机制和安全措施以确保数据传输的安全性和完整性。
在Android系统中Binder驱动的实现主要依赖于Linux内核提供的机制和功能。它利用Linux内核提供的虚拟文件系统、进程间通信IPC机制和内存管理功能实现了高效、可靠和安全的跨进程通信。
总之Binder驱动是Android操作系统中用于实现跨进程通信的重要机制之一它提供了高效、安全和灵活的通信方式使得应用程序的不同组件可以协同工作提高了应用程序的效率和性能。
那binder到底是个啥呢 Binder驱动相关的一些重要结构体
6~9 用于数据传输相关其中binder_write_readbinder_transaction_data进程空间和内核空间是通用的 /
Binder驱动是Android专用的但底层的驱动架构与Linux驱动一样。binder驱动在以misc设备进行注册作为虚拟字符设备没有直接操作硬件只是对设备内存的处理。主要是驱动设备的初始化(binder_init)打开 (binder_open)映射(binder_mmap)数据操作(binder_ioctl) 系统调用
用户态的程序调用Kernel层驱动是需要陷入内核态进行系统调用(syscall)比如打开Binder驱动方法的调用链为 open- __open() - binder_open()。 open()为用户空间的方法__open()便是系统调用中相应的处理方法通过查找对应调用到内核binder驱动的binder_open()方法至于其他的从用户态陷入内核态的流程也基本一致。
系统调用是操作系统提供给应用程序的一种接口使得应用程序可以使用操作系统的功能。通过系统调用应用程序可以请求操作系统的服务例如文件管理、进程控制、内存管理等。系统调用是应用程序与操作系统内核之间的接口它使得应用程序可以在用户空间和内核空间之间进行通信。
相关代码位置
内核主要是通过initcall机制在启动init进程的时候完成对binder_init()的调用 // debugfs_create_dir是指在debugfs文件系统中创建一个目录返回值是指向dentry的指针。当kernel中禁用debugfs的话返回值是-%ENODEV。默认是禁用的。如果需要打开在目录/kernel/arch/arm64/configs/下找到目标defconfig文件中添加一行CONFIG_DEBUG_FSy再重新编译版本即可打开debug_fs。 //在debugfs文件系统/sys/kernel/debug/中创建一系列的文件
//创建几个文件 // /sys/kernel/debug/binder/state // /sys/kernel/debug/binder/stats // /sys/kernel/debug/binder/transactions // /sys/kernel/debug/binder/transaction_log // /sys/kernel/debug/binder/failed_transaction_log /sys/kernel/debug/binder/state整体以及各个进程的thread/node/ref/buffer的状态信息如有deadnode也会打印 /sys/kernel/debug/binder/stats整体以及各个进程的线程数事务个数等的统计信息 /sys/kernel/debug/binder/failed_transaction_log记录32条最近的传输失败事件 /sys/kernel/debug/binder/transaction_log记录32条最近的传输事件 /sys/kernel/debug/binder/transactions遍历所有进程的buffer分配情况 proc目录中都是进程号观察其中的进程都是注册在驱动的进程其中包括servicemanager。可以通过命令cat /sys/kernel/debug/binder/proc/进程号查看对应进程的binder信息。 这只有进程号谁知道哪是哪啊 misc设备Linux内核把无法归类的设备定义为misc设备譬如看门狗、实时时钟等。Linux内核把所有的misc设备组织在一起构成一个子系统进行统一管理。在这个子系统里的所有misc类型的设备共享一个主设备号MISC_MAJOR(10)但它们次设备号不同。 结构体binder_device表示一个binder设备节点记录了该节点相关信息。 binder_device-miscdev即结构体miscdevice。它表示一个misc设备记录该设备的名称、次设备号、支持的系统调用操作等。 binder_device-miscdev.fops binder_fops; fops即file_operations结构体这个结构的每一个成员都对应着一个系统调用Linux系统调用通过调用file_operations中相应的函数指针接着把控制权转交给函数从而完成Linux设备驱动程序的工作
当binder驱动执行系统调用时即用户态像内核态的陷入 如果是系统调用ioctl()最终会调用binder_ioctl() 如果是系统调用mmap()最终会调用binder_map() 如果是系统调用open()最终会调用binder_open() binder文件系统——init_binderfs()
// 向VFS注册binder文件系统
int __init init_binderfs(void)
ret register_filesystem(binder_fs_type);
每个注册的文件系统都用一个类型为file_system_type的结构体表示。file_system_type主要记录文件系统的类型相关信息比如名称、上下文初始化函数指针等。binder_fs_type指明将要挂载的Binder文件系统名为binder 看来socket也整了一个文件系统 顺便带一下linux文件系统
详见参考链接 Binder文件系统挂载到VFS的时机在init进程启动的时候。相关挂载指令在system/core/rootdir/init.rc中
# Mount binderfs
mkdir /dev/binderfs
# 将代表Binder驱动的路径/dev/binderfs挂载到Binder文件系统。
mount binder binder /dev/binderfs statsglobal
chmod 0755 /dev/binderfs # 为相应的文件路径起别名。如/dev/binderfs/binder对应别名就是/dev/binder
symlink /dev/binderfs/binder /dev/binder symlink /dev/binderfs/hwbinder /dev/hwbinder symlink /dev/binderfs/vndbinder /dev/vndbinder
chmod 0666 /dev/binderfs/hwbinder chmod 0666 /dev/binderfs/binder chmod 0666 /dev/binderfs/vndbinder 还能这么玩儿
binderfs_binder_device_create()中inode-i_fop binder_fops。binder_fops是结构体file_operations的对象它记录着一些函数指针代表Binder文件系统支持的系统调用的最终实现
Framework层
每个要使用 Binder 进行通信的进程都会调用 Framework 层的 ProcessState::initWithDriver() 打开 Binder 驱动。initWithDriver() 主要涉及了几个系统调用它们的具体的实现主要是在内核层 mmap()进行 mmap 映射提供一块虚拟地址空间用于建立接收其他进程事务消息的缓冲区。最终会调用 Binder 驱动的 binder_mmap()
这几个系统调用最终都是通过虚拟文件系统进入到内核层
binder_open
在打开Binder设备时初始化并添加一个binder_proc结构体到全局链表中并创建相关的debugfs文件和binderfs文件 创建binder_proc对象并把当前进程等信息保存到binder_proc对象该对象管理IPC所需的各种信息并拥有其他结构体的根结构体再把binder_proc对象保存到文件指针filp以及把binder_proc加入到全局链表binder_procs Binder驱动中通过static HLIST_HEAD(binder_procs);创建了全局的哈希链表binder_procs用于保存所有的binder_proc队列每次新创建的binder_proc对象都会加入binder_procs链表中。
在当前进程在用户空间开辟了1M-8k的内存空间但是这些Binder线程会同时共享这部分空间都通过这部分空间来和Binder驱动进行传递数据。那么所以对于单个Binder线程能够传递的数据不会超过1M-8k Binder_mmap Binder_mmap实现
vma表示应用进程的虚拟地址空间。
通过mmap()机制让vma与某块物理页内存进行了映射。
同时让binder驱动内核的虚拟地址空间binder_proc-buffer与应用进程的虚拟内存大小一致
让该物理页与驱动的虚拟内存空间进行映射。
至此应用进程就和驱动内核映射了同一块物理空间应用进程可直接进行访问而不用拷贝
Binder 的内存管理指的就是管理 mmap 映射的这块缓冲区。Binder 驱动为这块缓冲区设计了复杂的数据结构实现了高效查询、分配 每个使用 Binder 通信的 Android 进程都会事先建立一个缓冲区。它用 binder_alloc 来管理。
binder_alloc 的部分定义如下 Binder 驱动用 binder_buffer 来描述缓冲区。但由于字节对齐缓冲区的大小可能会比这三个字段的总和稍大一点。Binder 驱动利用 buffers 链表采用了比较巧妙的方式计算一个 binder_buffer 的大小。Binder 驱动其实一开始是不会为缓冲区分配对应的物理内存的只是先分配了一段用户空间的虚拟地址即只是先分配了虚拟内存。 在处理事务的时候会从缓冲区划分一块 binder_buffer 出来处理事务。这时候才会为这块小缓冲区分配物理内存。
缓冲区分配的代码主要在 binder_alloc_new_buf_locked() 中 binder_buffer1 释放后由于 binder_buffer1 的前后都是空闲的 buffer会进行合并即 binder_buffer0、binder_buffer1 和 binder_buffer2 合并只剩 binder_buffer0。
② buffers 链表处理 发现 binder_buffer1 不是尾节点并且后续节点 binder_binder2 是空闲的直接移除 binder_buffer2 节点。 发现 binder_buffer1 不是头节点并且前驱节点 binder_binder0 是空闲的这时候移除的不是 binder_binder0而是 binder_buffer1 节点。
③ 在处理 buffers 链表的时候会同步更新 free_buffers 红黑树所以最终 free_buffers 红黑树只剩 binder_buffer0 节点。
④ 从 allocated_buffers 红黑树中移除 binder_buffer1。 分配、释放一个 binder_buffer 的物理内存页
分配、释放一个 binder_buffer 的物理内存页都是在 binder_update_page_range() 里进行的 链表结构体 binder_ioctl
ioctl是Linux中常见的系统调用它用于对底层设备的一些特性进行控制的用户态接口应用程序在调用ioctl进行设备控制时最后会调用到设备注册struct file_operations结构体对象的unlocked_ioctl或者compat_ioctl32位的应用运行在64位的内核上这个钩子被调用两个钩子上。在Binder驱动的struct file_operations定义中可见它的unlocked_ioctl钩子的的实现都是对应到binder_ioctl上的。
ioctl是Linux中常见的系统调用它用于对底层设备的一些特性进行控制的用户态接口应用程序在调用ioctl进行设备控制时最后会调用到设备注册struct file_operations结构体对象的unlocked_ioctl或者compat_ioctl32位的应用运行在64位的内核上这个钩子被调用两个钩子上。在Binder驱动的struct file_operations定义中可见它的unlocked_ioctl钩子的的实现都是对应到binder_ioctl上的。 参考链接
你真的知道什么是系统调用吗?这篇让你把它玩转起来 - 知乎
Binder系列1—Binder Driver初探 - Gityuan博客 | 袁辉辉的技术博客
图解 Binder内存管理 - 掘金
Binder Driver 5: binder_buffer 管理 - 简书
深入浅出文件系统二文件系统对象_file_system_type-CSDN博客