Android binder学习一:主要概念

要看得懂android代码,首先要了解binder机制。binder机制也是android里面比较难以理解的一块,这里记录一下binder的重要概念以及实现,作为备忘。部分内容来源于网上,如有侵权,请及时告知。

1.binder通信机制概述

binder通信是一种client-server的通信结构,
1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;
2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;
3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;
4.代理接口将该Parcel发送给内核中的binder driver.
5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;
6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。

binder_overview

2.为什么使用binder通信

linux中有管道,system V IPC,socket等进程间通信机制,那么为什么在android中使用了一个全新的binder通信机制呢?

一、可靠性。在移动设备上,通常采用基于Client-Server的通信方式来实现互联网与设备间的内部通信。目前linux支持IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket中只有socket支持Client-Server的通信方式。Android系统为开发者提供了丰富进程间通信的功能接口,媒体播放,传感器,无线传输。这些功能都由不同的server来管理。开发都只关心将自己应用程序的client与server的通信建立起来便可以使用这个服务。毫无疑问,如若在底层架设一套协议来实现Client-Server通信,增加了系统的复杂性。在资源有限的手机 上来实现这种复杂的环境,可靠性难以保证。

二、传输性能。socket主要用于跨网络的进程间通信和本机上进程间的通信,但传输效率低,开销大。消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的一块缓存区中,然后从内核缓存区拷贝到接收方缓存区,其过程至少有两次拷贝。虽然共享内存无需拷贝,但控制复杂。比较各种IPC方式的数据拷贝次数。共享内存:0次。Binder:1次。Socket/管道/消息队列:2次。

IPC 数据拷贝次数
共享内存 0
Binder 1
Socket/管道/消息队列 2

三、安全性。Android是一个开放式的平台,所以确保应用程序安全是很重要的。Android对每一个安装应用都分配了UID/PID,其中进程的UID是可用来鉴别进程身份。传统的只能由用户在数据包里填写UID/PID,这样不可靠,容易被恶意程序利用。而我们要求由内核来添加可靠的UID。

基于以上原因,Android需要建立一套新的IPC机制来满足系统对通信方式,传输性能和安全性的要求,这就是Binder。Binder基于Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。

3.service manager

顾名思义,service manager就是android下面管理service的一个进程,它本身也是一个service,这里的service和init.rc里面的service有一些差别,init.rc中的service都是一个进程,而这里的service可能不是一个单独的进程。每一个service在使用之前都必须向SM注册,每一个client要使用service前都应该先向SM查询是否存在这个service,如果存在,则给client返回这个service的handle。下面是sm中main函数的关键代码:

int main(int argc, char **argv)
{
    struct binder_state *bs;

    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    ......

    //svcmgr_handle的值为0
    svcmgr_handle = BINDER_SERVICE_MANAGER;
    binder_loop(bs, svcmgr_handler);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序
好的,下面是一个简单的 Android Binder Demo。 首先,我们定义一个 AIDL 接口文件 `IDemoService.aidl`,它包含一个方法 `int add(int a, int b)`,用于计算两个整数的和。 ```aidl // IDemoService.aidl interface IDemoService { int add(int a, int b); } ``` 然后,我们实现这个接口,创建一个名为 `DemoService` 的服务,它继承自 `IDemoService.Stub`,实现 `add()` 方法。 ```java // DemoService.java public class DemoService extends IDemoService.Stub { @Override public int add(int a, int b) throws RemoteException { return a + b; } } ``` 接下来,我们创建一个 `Service` `DemoServiceClass`,并在其中实现 `onBind()` 方法,返回 `DemoService` 对象。 ```java // DemoServiceClass.java public class DemoServiceClass extends Service { private DemoService demoService; @Override public void onCreate() { super.onCreate(); demoService = new DemoService(); } @Nullable @Override public IBinder onBind(Intent intent) { return demoService; } } ``` 最后,在 `AndroidManifest.xml` 中声明服务。 ```xml <!-- AndroidManifest.xml --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.binderdemo"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- 声明 DemoServiceClass --> <service android:name=".DemoServiceClass" /> <activity android:name=".MainActivity" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ``` 现在,我们可以在 `MainActivity` 中创建一个远程服务连接,调用 `add()` 方法并显示结果。 ```java // MainActivity.java public class MainActivity extends AppCompatActivity { private IDemoService demoService; private boolean connected = false; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { demoService = IDemoService.Stub.asInterface(iBinder); connected = true; } @Override public void onServiceDisconnected(ComponentName componentName) { demoService = null; connected = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, DemoServiceClass.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); Button button = findViewById(R.id.button); final TextView result = findViewById(R.id.result); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (connected) { try { int a = Integer.parseInt(((EditText) findViewById(R.id.input1)).getText().toString()); int b = Integer.parseInt(((EditText) findViewById(R.id.input2)).getText().toString()); int sum = demoService.add(a, b); result.setText(String.valueOf(sum)); } catch (RemoteException e) { e.printStackTrace(); } } else { result.setText("Service not connected"); } } }); } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); } } ``` 这就是一个简单的 Android Binder Demo。它演示了如何创建一个远程服务,实现 AIDL 接口并将其绑定到 Activity。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值