binder浅析

众所周知Binder 是Android中的一种跨进程通信方式,从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager,WindowManager等等)和相应ManagerService的桥梁;从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当是在不同的进程间通信时,服务端会返回一个bindService的代理对象,在同进程通信时,服务端会返回本地的一个bindService对象,同时Binder对象默认也继承了安卓智能指针类,框进程通信如图:
diagram
那么Binder驱动中,Binder对象引用有以下两种:

  • 在同一个进程中,Binder对象的一个真实的虚拟地址
  • 在另外一个进程中的,Binder对象的一个抽象的32位handle

因此在每个事务中,Binder驱动都会自动的将远程的binder handle映射成本地的地址,将本地的地址映射成远程的Binder handle,为更好的维护和管理Binder对象,其借助了一下几点:

  • binder驱动在进程之间维持本地地址和远程handle(每一个进程都作为一个二进制树),因此,binder可以传送.
  • 一旦一个新的Binder对象引用在事务中被发现,它就会记录在Binder驱动中.
  • 任何时候,Binder引用与其它的进程共享,Binder驱动的引用计数器就会增长.
  • 当进程消亡的时候,Binder驱动的计数器就会明确的减少或自动地减少.
  • 当一个引用不再需要的时候,它的所有者就会提醒它可以释放掉,并且Binder会删除自己的映射.
    接下来写一个基于Binder的服务端和客户端,其通信过程如图:
    building_a_binder_01
    其服务端的binder实体:

    /**
    * @Author: beyondboy
    * @Gmail: guoli.xgl@alibaba-inc.com
    * @Date: 2016-05-20
    * @Time: 19:21
    * 服务端的binder对象
    */
    public class IFibonacciServiceImpl extends  IFibonacciService.Stub{
    private static final String TAG = "IFibonacciServiceImpl";
    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
    
    }
    
    @Override
    public long fibJR(long n) throws RemoteException {
        Log.d(TAG, String.format("fibJR(%d)", n));
        return FibLib.fibJR(n);
    }
    
    @Override
    public long fibJI(long n) throws RemoteException {
        Log.d(TAG, String.format("fibJI(%d)", n));
        return FibLib.fibJI(n);
    }
    
    @Override
    public long fibNR(long n) throws RemoteException {
        Log.d(TAG, String.format("fibNR(%d)", n));
        return FibLib.fibNR(n);
    }
    
    @Override
    public long fibNI(long n) throws RemoteException {
        Log.d(TAG, String.format("fibNI(%d)", n));
        return FibLib.fibNI(n);
    }
    
    /**返回响应给客户端*/
    @Override
    public FibonacciResponse fib(FibonacciRequest request) throws RemoteException {
        Log.d(TAG,
                String.format("fib(%d, %s)", request.getN(), request.getType()));
        long timeInMillis = SystemClock.uptimeMillis();
        long result;
        switch (request.getType()) {
            case ITERATIVE_JAVA:
                result = this.fibJI(request.getN());
                break;
            case RECURSIVE_JAVA:
                result = this.fibJR(request.getN());
                break;
            case ITERATIVE_NATIVE:
                result = this.fibNI(request.getN());
                break;
            case RECURSIVE_NATIVE:
                result = this.fibNR(request.getN());
                break;
            default:
                return null;
        }
        timeInMillis = SystemClock.uptimeMillis() - timeInMillis;
        return new FibonacciResponse(result, timeInMillis) {
        };
    }
    }
    

    服务端实体:

    /**
    * @Author: beyondboy
    * @Gmail: guoli.xgl@alibaba-inc.com
    * @Date: 2016-05-20
    * @Time: 20:38
    * binder服务端
    */
    public class FibonacciService extends Service {
    private static final String TAG = "FibonacciService";
    
    private IFibonacciServiceImpl service;
    
    @Override
    public void onCreate() {
        super.onCreate();
        this.service = new IFibonacciServiceImpl();
        Log.d(TAG, "onCreate()'ed");
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind()'ed");
        return this.service;
    }
    
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind()'ed");
        return super.onUnbind(intent);
    }
    
    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy()'ed");
        this.service = null;
        super.onDestroy();
    }
    }
    

    客户端实体:

    /**
    * @Author: beyondboy
    * @Gmail: guoli.lxgl@alibaba-inc.com
    * @Date: 2016-05-21
    * @Time: 12:42
    * 客户端
    */
    public class FibonacciActivity extends Activity implements View.OnClickListener,ServiceConnection{
    private static final String TAG = "FibonacciActivity";
    
    private EditText input;
    
    private Button button; // 触发非波那契數列的计算
    
    private RadioGroup type; // 非波那契數列实现类型
    
    private TextView output; // 输出非波那契數列的计算结果
    
    private IFibonacciService service; // 引用非波那契數列的服务
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.main);
        this.input = (EditText) super.findViewById(R.id.input);
        this.button = (Button) super.findViewById(R.id.button);
        this.type = (RadioGroup) super.findViewById(R.id.type);
        this.output = (TextView) super.findViewById(R.id.output);
        this.button.setOnClickListener(this);
        // 当我们链接上我们的服务才让按钮变为可按
        this.button.setEnabled(false);
    }
    
    @Override
    protected void onResume() {
      //  Log.d(TAG, "onResume()'ed");
        super.onResume();
        Intent intent=new Intent(this, FibonacciService.class);
       // intent.addCategory(Intent.CATEGORY_DEFAULT);
        //开启服务
        if (!super.bindService(intent,
                this, BIND_AUTO_CREATE)) {
            Log.w(TAG, "Failed to bind to service");
        }
    }
    
    @Override
    protected void onPause() {
        Log.d(TAG, "onPause()'ed");
        super.onPause();
        //停止服务
        super.unbindService(this);
    }
    
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "onServiceConnected()'ed to " + name);
        // 获得我们的IFibonacciService
        this.service = IFibonacciService.Stub.asInterface(service);
        this.button.setEnabled(true);
    }
    
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "onServiceDisconnected()'ed to " + name);
        this.service = null;
        this.button.setEnabled(false);
    }
    
    public void onClick(View view) {
        final long n;
        String s = this.input.getText().toString();
        if (TextUtils.isEmpty(s)) {
            return;
        }
        try {
            n = Long.parseLong(s);
        } catch (NumberFormatException e) {
            this.input.setError(super.getText(R.string.input_error));
            return;
        }
    
        final FibonacciRequest.Type type;
        switch (FibonacciActivity.this.type.getCheckedRadioButtonId()) {
            case R.id.type_fib_jr:
                type = FibonacciRequest.Type.RECURSIVE_JAVA;
                break;
            case R.id.type_fib_ji:
                type = FibonacciRequest.Type.ITERATIVE_JAVA;
                break;
            case R.id.type_fib_nr:
                type = FibonacciRequest.Type.RECURSIVE_NATIVE;
                break;
            case R.id.type_fib_ni:
                type = FibonacciRequest.Type.ITERATIVE_NATIVE;
                break;
            default:
                return;
        }
        final FibonacciRequest request = new FibonacciRequest(n, type);
    
        // 展示计算进度
        final ProgressDialog dialog = ProgressDialog.show(this, "",
                super.getText(R.string.progress_text), true);
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                try {
                    long totalTime = SystemClock.uptimeMillis();
                    FibonacciResponse response = FibonacciActivity.this.service
                            .fib(request);
                    totalTime = SystemClock.uptimeMillis() - totalTime;
                    // 获取结果
                    return String.format(Locale.ENGLISH,
                            "fibonacci(%d)=%d\nin %d ms\n(+ %d ms)", n,
                            response.getResult(), response.getTimeInMillis(),
                            totalTime - response.getTimeInMillis());
                } catch (RemoteException e) {
                    Log.wtf(TAG, "Failed to communicate with the service", e);
                    return null;
                }
            }
    
            @Override
            protected void onPostExecute(String result) {
                dialog.dismiss();
                if (result == null) {
                    // 处理错误
                    Toast.makeText(FibonacciActivity.this, R.string.fib_error,
                            Toast.LENGTH_SHORT).show();
                } else {
                    // 展示结果
                    FibonacciActivity.this.output.setText(result);
                }
            }
        }.execute();
    }
    
    }
    

    demo链接如下:
    https://github.com/scau-beyondboy/BinderSynDemo.git
    其大致结构如图:
    __040
    __041
    在binder通信中,有个重要细节:
    客户端和服务端都位于同一个进程时,其通信不会通过Stub的内部代理类Proxy来完成,也就是说方法调用不会走跨进程的transact过程,而当两者位于不同进程时,会通过内部代理类的Proxy的transact过程。

    //Construct the stub at attach it to the interface. 
    public Stub()
    {
    //存储此binder子类对象到本地进程的binder节点树中
    this.attachInterface(this, DESCRIPTOR);
    }
    // Cast an IBinder object into an com.scau.beyondboy.bindercommon.IFibonacciService interface,
    //generating a proxy if needed.
    public static com.scau.beyondboy.bindercommon.IFibonacciService asInterface(android.os.IBinder obj)
    {
    if ((obj == null)) {
        return null;
    }
    //从本进程binder节点树中查找
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.scau.beyondboy.bindercommon.IFibonacciService))) {
        return ((com.scau.beyondboy.bindercommon.IFibonacciService) iin);
    }
    //创建其binder代理对象暴露给另一个进程使用其服务
    return new com.scau.beyondboy.IFibonacciService.Stub.Proxy(obj);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
binder_open是Binder机制中的一个函数,用于打开Binder驱动并返回一个Binder状态结构体。在该函数中,会调用copy_from_user函数从用户空间获取一个struct binder_write_read结构体,并将其作为参数传递给binder_thread_write和binder_thread_read函数。\[1\] 在Binder机制的Native层实现中,binder_open函数被用于开启Binder,并将自身注册为Binder进程的上下文,然后通过调用binder_loop函数来启动Binder循环。\[2\] 在binder_loop函数中,如果收到了Binder的读写消息信息,会调用binder_parse函数进行处理。binder_parse函数会将读取到的消息进行解析,并调用相应的处理函数进行处理。\[3\] #### 引用[.reference_title] - *1* [05.Binder系统:第6课第2节_Binder系统_驱动情景分析_打印数据交互过](https://blog.csdn.net/weixin_43013761/article/details/88171380)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【Binder 机制】Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse )](https://blog.csdn.net/han1202012/article/details/120345228)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值