在说明Binder之前。我们来想想Binder作为一个进程间通信的通道之前。我们常用的进程间通信有几种。

Linux中,我们常见有一下几种进程间通信:

1.pipe 管道

2.FIFO named pipe 有名管道

3.signal 信号

4.消息队列

5.socket 套子节

6.SharedMemory 共享内存

用户空间(用户态)和内核空间(内核态)

一些操作系统允许所有用户与硬件做交互。但是,类unix操作系统在用户应用程序钱把计算机物理组织相关的底层细节都隐藏起来。当程序想试用硬件资源时候,必须向操作系统发出请求。内核会对这个请求做评估,允许使用,那么内核将会代表应用与硬件交互。 为了实现这个机制,现代操作系统依赖特殊硬件特性来禁止用户程序直接与底层打交道,或者直接访问任意的物理地址。硬件为cpu引入了至少两种执行模式:用户的非特权模式和内核的特权模式。也就是我们常说的用户态和内核态。

这是来自深入理解Linux一书中的定义。举个简单的例子,当我们需要运行文件操作的时候,使用open等操作方法,就会从用户程序就会从用户态进入到内核态,当open结束之后,用户程序进入回到用户态。

为什么Linux系统要这么设计。最大的原因就是为了让内核底层透明化,同时如果用户程序出现了问题,将不会影响内核。

换我们思考一下,如果是我们,怎么在两个隔离的进程任务块中联系彼此。很常见的一个思路,我们一般能想到的是,让一个进程把需要交互的信息存到一个文件里面,另一个进程从文件中读取数据。

管道pipe

这种思路,被广泛运用到Linux系统中。比如pipe实际上是创建了两个文件(文件描述符实际上是内核缓存区),一个专门用来读,一个专门用来写。而pipe是一个半双工的通道,换句话说就是在一个时间内只能在一个单方向的进程通信。这样就可能的减少因为多个进程来回竞争文件内容,导致传输过程中出错。

而此时pipe必定是先通过内核调用copy_from_user方法把初始化数据拷贝一份内核空间中,此时通过alloc_file通过kmalloc在调用slab在内核空间创建2个文件描述符。

大致上示意图如下:

记住fd[0]是读通道,fd[1] 是写通道

FIFO named pipe

有名管道,这中管道在原来的基础上做了处理,依赖了Linux的文件系统。从名字上就能得出这种管道是先入先出的原则,能够让数据通信按照顺序来。然而有名管道更大的意义是让管道命名。原来的管道是无名管道,所以只能在自己控制下的子进程做沟通。而多了名字之后,就不需要想法子把地址交给第二个进程,而是通过名字去找文件,就能建立通道。

signal 信号

信号这个东西,我们其实早就有所耳闻。比如说我们常说的中断信号就是指的是信号的一种。而在linux内核中内置一些通知事件。每一次发出这个事件内核将会通知进程接收这些事件,并且做处理。

内核实现:

1.为了做到对应的信号能够发送到正确需要进程。内核需要记住当前进程被哪些信号阻塞。

2.当从内核态切换到用户态,检查进程是否产生信号。这种检测每个时钟都会触发一次,一般在几个毫秒内触发一次。

3.还要检测哪些信号被忽略。以下条件都满足时表示信号被忽略

  • 进程没有被追踪,task_struct(用来描述进程的结构体)PT_PTRACED标示为0.

  • 进程没有阻塞这种信号

  • 进程忽略这种信号

4.处理信号

此时我们需要注意的是,在内核态我们是不会处理信号的,往往都会抛到用户空间,通过copy_to_user拷贝交给用户空间去处理。

消息队列

这个听起来有点像Android里面的消息队列。两者相比,设计上确实相似。消息队列的使用,先通过ftok生成一个key,再通过key用msgget创建一个消息队列(文件)。之后用msgsnd或者msgrcv发送或者接收东西。

此时在内核上实际上可以看出创建了一个文件。把对应的消息传进去消息队列中。此时读取方和写入方由于有ftok生成一个key,就能在内核空间找到对应的消息队,就能借助这个队列完成消息的传递。其中为了让数据能够来回在用户态和内核态来回切换,还是使用到了copy _from_user,copy_to_user.其数据结构是一个链表。

socket 套子节

这个我们所有人都十分的熟悉。我们做网络编程离不开它。实际上从原理上它也是一种特殊的文件,我们也是不断的监听socket的状态来回应。既然是文件操作,那么一定会经历一次用户态到内核态,内核态到用户态的转化。这种本地监听的运用,在zyogte孵化进程的时候经常用。

共享内存

共享内存的设计,是最接近binder的设计。其核心也是用过mmap内存映射技术。其设计上也和消息队列相似。也是通过ftok生成一个key,再通过这个key申请内存shmget之后,就能对这段地址做操作。

信号量

实际上信号量最主要的作用是对进程进行加锁,如果有进程访问这个正在使用的资源会进入睡眠状态。

Binder 的概述

介绍了Linux的几种基础IPC(进程间通信),我们发现一个很有趣的现象。大部分的IPC通信都通过文件作为中转站来回通讯。这样势必会造成用户态,内核态在来回切换,那么必定造成这种数据拷贝两次的情况。那么我们有没有办法处理优化这种通信方法呢?Binder就诞生了。

那么我们要设计Binder的话,又能怎么设计呢?首先为了让整个透明并且可靠化,我们能采用TCP/IP这一套思路来保证信息的可靠性。其次为了减少来回的在用户往内核中拷贝空间能够创造模仿共享内存的方式。

我们可以关注到Binder中四种角色:

Binder 驱动

ServiceManager

Binder Client

Binder Service

从这里我们明白,在内核空间中,存在这一个Binder的驱动,而这个驱动正是作为整个IPC通信的中转站。也就是类似TCP通信中的路由地位,我不在乎你究竟要是干啥,我只需要找到你,并且把消息交给你就好。

此时service manager充当的是Binder驱动的守护进程,类似于TCP通信中的DNS地位。我们会把相关的Binder注册到里面,最后会通过service manager这个服务去查找binder的远程端。而实际上这个service manager在Andrioid Binder体系中,承当了Android系统中第一个注册进入Binder的服务。

Binder Client binder的客户端,相当于C/S架构中的客户端的概念。

Binder Service binder的服务端,相当于C/S架构中中服务端的概念。

Binder驱动,本身充当一个一个类似路由表,路由分发器。每当一个client想去寻找service的时候,都会经过binder驱动,binder并不关心传输的内容是什么,只需要帮助你分发到服务。

在这里我重新申明一次,所谓的服务端和客户端的概念只是为了更加好理解,实际上在Binder驱动看来并没有所谓的服务和客户端概念,仅仅只有远程端(或者代理端)和本地端的概念。因此Binder在整个IPC进程通信中,谁发出了请求此时就是作为本地端也就是客户端,而远程响应这个请求的则是代理端/远程端,也就是上面说的服务端。

大致知道这些角色之后,也就能清楚上方这个图的意义了。很简单,在Android系统启动的时候,会去启动一个Service Manager的进程。而这个进程会初始化好内核的Binder驱动。此时DNS和路由都准备好了。只要等到服务端注册进来,客户端取链接交互即可。

下面是根据binder的设计的示意图。

为什么我说Binder和TCP十分相似。首先在我们开发中从来不会注意到binder的存在,更加不会注意到Android开发中我们居然会有信息做了跨进程通信。这也侧面说明了binder的设计优秀以及binder已经对上层来说几乎透明化。

那么让我们略去service manager 和binder 驱动看看service和client之间的关系。

Binder驱动的初始化 syscall原理(一)相关推荐

  1. Android Binder驱动的工作机制之要旨

    最近,看了不少Android内核分析的书籍.文章及Android源程序.感觉自己对Android Binder的工作机制算是有了个彻底的理解. 但是,自己是花了很多时间和精力之后才达到这一点的.对于大 ...

  2. Android10.0 Binder通信原理(五)-Binder驱动分析

    摘要:本节主要来讲解Android10.0 Binder的驱动层分析 阅读本文大约需要花费35分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计 ...

  3. Binder驱动与协议(二)

    "九层之台,始于垒土:千里之行,始于足下",不论binder机制在Android源码中多庞大繁杂,总归它得从地基开始–Binder驱动,我们知道Android系统是基于Linux的 ...

  4. Binder 驱动详解(下)

    前言 通过 Binder 上一篇文章的分析, 我们知道了 Binder 驱动在我们应用开发过程中的使用方式, 了解到了 BBinder 和 BpBinder 两个非常重要的 Native 对象, 本次 ...

  5. 深入分析Android Binder 驱动

    Android Binder是一种在Android里广泛使用的一种远程过程调用接口.从结构上来说Android Binder系统是一种服务器/客户机模式,包括Binder Server.Binder ...

  6. Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理

    JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...

  7. RK WiFi驱动层初始化分析

    RK3368 默认支持的WiFi芯片为AP6XXX系列,此芯片还默认支持BT. 可以先看看原理图里面的的情况,方便我们理解其在代码里面的配置情况 WiFi 设备配置: ./rockchip/rk336 ...

  8. 重磅直播|ORB-SLAM3经典单目初始化模块原理及实现

    点击上方"计算机视觉工坊",选择"星标" 干货第一时间送达 大家好,本公众号现已开启线上视频公开课,主讲人通过B站直播间,对3D视觉领域相关知识点进行讲解,并在 ...

  9. scsi总线驱动的初始化

    1.6.1 scsi总线驱动的初始化 块设备底层驱动的核心是scsi总线层驱动,在总线层驱动之上为各种不同的scsi设备驱动,在总线层驱动之下为scsi host驱动.其在内核中的位置如下图所示: 前 ...

  10. 2020-12-08图腾柱驱动的作用与原理分析

    图腾柱驱动的作用与原理分析 电子设计•作者:电子设计 • 2018-10-08 07:27 • 65048次阅读  0 由于此结构画出的电路图有点儿像印第安人的图腾柱,所以叫图腾柱式输出(也叫图腾式输 ...

最新文章

  1. linux升级apache版本,Apache2.4版本的安装或升级常见错误
  2. 魔兽转服务器有什么影响,魔兽怀旧服:免费转出是败笔,牺牲了大部分服务器,成全为两个服...
  3. 想要自学深度学习?不用GPU,浏览器就够了
  4. nginx访问控制:如何通过map来控制http_x_forwarded_for访问限制
  5. MoeCTF 2021Re部分------RedC4Bomb
  6. SpringBoot 封装返回类以及session 添加获取
  7. 如何取得select结果数据集的前10条记录。postgresql
  8. java一行交换,在C / C ++,Python,PHP和Java中一行交换两个变量
  9. 内核与ramdisk到底是什么关系
  10. rpm软件包管理的详细解读
  11. ByPass Mode(略过模式或旁路模式)
  12. Azylee.Utils 工具组
  13. html- 颜色代码
  14. oppo计算机找不到,oppo手机和电脑连接不上怎么办只显示充电(原来这个功能没有打开)...
  15. godot引擎学习10
  16. 我的钱包页面HTML,钱包.html
  17. MYSQL数据库----删除命令
  18. clk_mux及对应的约束
  19. 神经网络图像细节分析,神经网络 图像相似度
  20. 激光测距仪系统设计 c语言程序),基于时差法的激光测距方法与应用

热门文章

  1. magento mage.php,Magento源码分析笔录二:Mage.php主要枢纽类
  2. 失败的国产游戏《血狮》
  3. 网络安全防护中的重大缺失!缺少了对人的防护
  4. 深度学习实战56-基于VR虚拟现实眼镜与计算机视觉远程操控机器人,实现远程协助独居老人生活起居
  5. 什么才算是真正的编程能力?
  6. 梦想世界3手游服务器维护,“沧海秘宝”新服成长指南!《梦想世界3》手游开启盛夏狂欢...
  7. 文件压缩下载的时候 边压缩边下载
  8. 2022大连理工大学《矩阵上机作业》秋(部分题)(by 徐靖昌)
  9. 【Chales】使用 Charles 解决部分App无法上网的问题(SSL Pinning)
  10. 使用芯愿景软件提数字电路方法(适合初学者)