Binder駆動のdebug情報とデータ構造


Binder debugや問題の解析を行う場合は、通常、現在のBinderステータス情報を見る必要があります.KernelはSYSシステムを通じて、/sys/kernel/debug/binder/、それぞれ:
  • State:現在のBinderのすべてのプロセスのステータス.
  • Stats:Binder転送の統計.
  • Transactions:現在のBinderのすべてのプロセスの転送ステータス.
  • transaction_log:最近のBinder転送.
  • failed_transaction_log:最近失敗したBinder転送.

  • これらのDebug情報を理解するには、Binderドライバに関連するデータ構造定義が必要です.これらの情報はほとんど駆動中のすべての構造体に関連しており,以下,両者を組み合わせて情報の具体的な内容を見る.まず、Binderドライバの最も基本的なデータ構造binder_を見てみましょう.proc.Binder_procはBinderプロセスを記述するためのデータ構造であり、1つのプロセスには1つのbinder_しかない.Procは、他の構造体がこのデータ構造に関連付けられます.つまりbinder_Procは、Binderスレッド、Binderリファレンス、Binderメモリなど、すべてのBinderプロセスに関する情報を検索できます.
    struct binder_proc {
        struct hlist_node proc_node; /* hlist  ,       binder_procs  */
        struct rb_root threads; /* Binder       */
        struct rb_root nodes; /* Binder       */
        struct rb_root refs_by_desc; /* Binder      , handle key */
        struct rb_root refs_by_node; /* Binder      , node   key */
        int pid; /*   PID */
        struct vm_area_struct *vma; /*            */
        struct mm_struct *vma_vm_mm; /*        */
        struct task_struct *tsk; /*   task   */
        struct files_struct *files; /*   file   */
        struct hlist_node deferred_work_node; /* hlist  ,       binder_deferred_list ,    binder     */
        int deferred_work; /* Binder defer flag,  PUT_FILES,FLUSH,RELEASE */
        void *buffer; /* Binder         */
        ptrdiff_t user_buffer_offset; /* Binder               */
    
        struct list_head buffers; /* Binder buffer    */
        struct rb_root free_buffers; /*   Binder buffer     */
        struct rb_root allocated_buffers; /*    Binder buffer     */
        size_t free_async_space; /*           */
    
        struct page **pages; /*       */
        size_t buffer_size; /* Binder        */
        uint32_t buffer_free; /* Binder        */
        struct list_head todo; /* Binder   todo   */
        wait_queue_head_t wait; /* Binder        */
        struct binder_stats stats; /* Binder     */
        struct list_head delivered_death; /* Binder         */
        int max_threads; /* Binder         */
        int requested_threads; /*        */
        int requested_threads_started; /*           */
        int ready_threads; /*          */
        long default_priority; /*       */
        struct dentry *debugfs_entry; /* debugfs   */
    };

    State
    Stateが最初に記録したときに死亡したBinder(dead node).これらのBinderのプロセスはすでに死んでおり、現在はどのプロセスにも属していないため、グローバルなキューに記録されている(binder_dead_nodes).死亡記録は以下のように示されている.
    Dead nodesに関するデータ構造はbinder_node,binder_Nodeはbinderエンティティを表します.プロセス内のbinder_NodeはProcのnodesレッドブラックツリーによって管理され、死亡したbinder_Nodeはグローバルhlist binder_によってdead_Nodes管理、もう一つのグローバルbinder_context_mgr_nodeはsystem_を記録するために使用されますserverのbinder_node.定義は次のとおりです.
    struct binder_node {                                        
            int debug_id; /* binder node       id,     */
            struct binder_work work; /* binder    。    /  binder,  binder     */
            union {    
                    struct rb_node rb_node; /* Proc nodes     rb_node */                
                    struct hlist_node dead_node; /*    binder_node,        ,  binder    。             binder, binder node    ,  dead node */
            };                                        
            struct binder_proc *proc; /* binder node      */
            struct hlist_head refs; /* binder node     ,    binder node      */
            int internal_strong_refs; /* binder node         */    
            int local_weak_refs; /*      binder      */
            int local_strong_refs; /*      binder      */
            void __user *ptr; /*       binder   ,     */
            void __user *cookie; /*           */    
            unsigned has_strong_ref:1; /*        */
            unsigned pending_strong_ref:1; /*             */    
            unsigned has_weak_ref:1; /*        */
            unsigned pending_weak_ref:1; /*             */
            unsigned has_async_transaction:1; /*  Todo               */
            unsigned accept_fds:1;     /*            binder*/
            unsigned min_priority:8; /*     Binder            */
            struct list_head async_todo; /*          */
    }

    Dead nodes情報の後には、現在のシステム内のすべてのBinderプロセスの情報が続きます.この情報には、プロセス内のBinderスレッドの状態、Binderエンティティ情報、Binderリファレンス情報、binder buffer情報が含まれます.
    スレッドステータスBinderプロセス内のすべてのBinderスレッドのPIDとスレッドステータス、binder_threadデータ構造とスレッド状態は以下のように定義される.
    enum {
        BINDER_LOOPER_STATE_REGISTERED  = 0x01, /*     (BC_REGISTER_LOOPER) */
        BINDER_LOOPER_STATE_ENTERED     = 0x02, /*      (BC_ENTER_LOOPER) */
        BINDER_LOOPER_STATE_EXITED      = 0x04, /*     */
        BINDER_LOOPER_STATE_INVALID     = 0x08, /*    */
        BINDER_LOOPER_STATE_WAITING     = 0x10, /*     */
        BINDER_LOOPER_STATE_NEED_RETURN = 0x20 /*      */
    };
    
    struct binder_thread {
        struct binder_proc *proc; /*          */
        struct rb_node rb_node; /*      ,   binder_proc->threads  */
        int pid; /*   PID */
        int looper; /*   looper  ,         */
        struct binder_transaction *transaction_stack; /* Binder    */
        struct list_head todo; /* Binder  todo   */
        uint32_t return_error; /*            */
        uint32_t return_error2; /*           2 */
        wait_queue_head_t wait; /* Binder       */
        struct binder_stats stats; /* Binder       */
    };

    次に、BinderプロセスにおけるBinderエンティティの情報を説明し、Dead nodesを参照します.次に印刷されるのは、プロセス中にBinderが参照する情報であり、関連データ構造はbinder_である.refは、Binderエンティティのエージェントとして使用されます.
    struct binder_ref {
        /* Lookups needed: */
        /*   node + proc => ref (transaction) */
        /*   desc + proc => ref (transaction, inc/dec ref) */
        /*   node => refs + procs (proc exit) */
        int debug_id;  /*   id,     */
        struct rb_node rb_node_desc; /*      ,  binder_proc->refs_by_desc */
        struct rb_node rb_node_node; /*      ,  binder_proc->refs_by_node */
        struct hlist_node node_entry; /* hlist  ,  binder_node->refs   */
        struct binder_proc *proc; /*    Binder    */
        struct binder_node *node; /*    Binder   */
        uint32_t desc; /* handle  */
        int strong; /*     */
        int weak; /*     */
        struct binder_ref_death *death; /*            */
    };

    最後にBinderプロセスにおけるBinder bufferの情報.関連データ構造はbinder_Binder転送データを格納するbuffer.
    struct binder_buffer {
        struct list_head entry; /* list  ,   binder_proc->buffers */
        struct rb_node rb_node; /*      ,   binder_proc->free_buffers(buffer   ) binder_proc->allocated_buffers(buffer    ) */
        unsigned free:1; /*      */
        unsigned allow_user_free:1; /*          */
        unsigned async_transaction:1; /*         */
        unsigned debug_id:29; /*   id,     */
        struct binder_transaction *transaction; /*    Binder     */
        struct binder_node *target_node; /*    Binder   */
        size_t data_size; /*      */
        size_t offsets_size; /*       */
        uint8_t data[0]; /*      */
    }

    Stats
    Statsには,転送命令の統計,内部オブジェクトの統計などを含むBinderの統計が含まれる.最初に出力されるのはすべてのBinderの統計で、その後Binderプロセスごとに統計を出力します.出力例は次のとおりです.
    Binder統計binder_を介してstatsで表すと、
    struct binder_stats {         
        int br[_IOC_NR(BR_FAILED_REPLY) + 1]; /* Binder         (Binder Driver Return Protocol)*/
        int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1]; /* Binder        (Binder Driver Command Protocol)*/
        int obj_created[BINDER_STAT_COUNT]; /* Binder        ,    1 */
        int obj_deleted[BINDER_STAT_COUNT]; /* Binder        ,    1 */
    }; 

    BC_で先頭のコマンドは、アプリケーション層がBinderドライバに送信するリクエストコマンドであり、以下のように定義されている.
    Cmd
    Description
    Args
    Code
    BC_TRANSACTION
    Clientがサーバに要求データを送信
    binder_transaction_data: the sent command
    10763886080x40286300
    BC_REPLY
    ServerがClientに返信(応答)データを送信
    binder_transaction_data: the sent command
    10763886090x40286301
    BC_ACQUIRE_RESULT
    まだ実現していない
    ---
    10740293140x40046302
    BC_FREE_BUFFER
    マッピングされたメモリを解放します.
    void *: ptr to transaction data received on a read
    10740293150x40046303
    BC_INCREFS
    Binderの弱い参照数を増やす
    int: descriptor
    10740293160x40046304
    BC_ACQUIRE
    Binderの強い参照数を増やす
    int: descriptor
    10740293170x40046305
    BC_RELEASE
    Binderの強い参照数を減らす
    int: descriptor
    10740293180x40046306
    BC_DECREFS
    Binderの弱い参照数を減らす
    int: descriptor
    10740293190x40046307
    BC_INCREFS_DONE
    BindeエンティティのプロセスがBC_を処理しました.INCREFSのフィードバック
    void : ptr to bindervoid : cookie
    10742914640x40086308
    BC_ACQUIRE_DONE
    BindeエンティティのプロセスがBC_を処理しました.ACQUIREのフィードバック
    void : ptr to bindervoid : cookie
    10742914650x40086309
    BC_ATTEMPT_ACQUIRE
    まだ実現していない
    ---
    10742914660x4008630a
    BC_REGISTER_LOOPER
    通知ドライバスレッドプールのスレッドが作成されました
    ---
    253550x630b
    BC_ENTER_LOOPER
    スレッドがプライマリサイクルに入ったことを通知し、データを受信できます.
    ---
    253560x630c
    BC_EXIT_LOOPER
    通知は、スレッドがプライマリサイクルを終了し、データを受信しないように駆動します.
    ---
    253570x630d
    BC_REQUEST_DEATH_NOTIFICATION
    Binderが参照するプロセスでは、Binderのエンティティの死亡通知を取得する必要があります.
    void : ptr to bindervoid : cookie
    10742914700x4008630e
    BC_CLEAR_DEATH_NOTIFICATION
    Binderを取得したエンティティの死亡通知をクリア
    void : ptr to bindervoid : cookie
    10742914710x4008630f
    BC_DEAD_BINDER_DONE
    エンティティの死亡通知書を受信したプロセスは、参照を削除した後、本コマンドでドライバに通知します.
    void *: cookie
    10740293280x40046310
    BR_で先頭のコマンドは、Binderドライバがアプリケーション層に送信する返信コマンドであり、以下のように定義されている.
    Cmd
    Description
    Args
    Code
    BR_ERROR
    メモリの割り当てに失敗したなど、内部エラーが発生しました.
    int: error code
    21477749760x80047200
    BR_OK
    操作完了
    ---
    291850x7201
    BR_TRANSACTION
    送信元のBC_に対応TRANSACTION
    binder_transaction_data: the received command
    21501342740x80287202
    BR_REPLY
    送信元のBC_に対応REPLY
    binder_transaction_data: the received command
    21501342750x80287203
    BR_ACQUIRE_RESULT
    まだ実現していない
    ---
    21477749800x80047204
    BR_DEAD_REPLY
    インタラクション中に相手のプロセスまたはスレッドが死亡していることが判明した場合、メッセージを返します.
    ---
    291890x7205
    BR_TRANSACTION_COMPLETE
    受信者は、このメッセージをBC_として送信するTRANSACTIONまたはBC_REPLY送信成功のフィードバック
    ---
    291900x7206
    BR_INCREFS
    Binderローカルオブジェクトの弱い参照数を増やす
    void : ptr to bindervoid : cookie for binder
    21480371270x80287207
    BR_ACQUIRE
    Binderローカルオブジェクトの強い参照数を増やす
    void : ptr to bindervoid : cookie for binder
    21480371280x80287208
    BR_RELEASE
    Binderローカルオブジェクトの強い参照数を減らす
    void : ptr to bindervoid : cookie for binder
    21480371290x80287209
    BR_DECREFS
    Binderローカルオブジェクトの弱い参照数を減らす
    void : ptr to bindervoid : cookie for binder
    21480371300x8028720a
    BR_ACQUIRE_RESULT
    まだ実現していない
    ---
    21482992750x800c720b
    BR_NOOP
    仕事をしないで、
    ---
    291960x720c
    BR_SPAWN_LOOPER
    ドライバは、受信者のすべてのスレッドがビジー状態であることを発見し、受信データに備えてより多くのスレッドを作成する必要があることを受信者に送信します.
    ---
    291970x720d
    BR_FINISHED
    まだ実現していない
    ---
    291980x720e
    BR_DEAD_BINDER
    Binderエンティティの死亡通知をBinderリファレンスを取得するプロセスに送信
    void **cookie
    21477749910x8004720f
    BR_CLEAR_DEATH_NOTIFICATION_DONE
    死亡通知クリア完了
    void **cookie
    21477749920x80047210
    BR_FAILED_REPLY
    不正な参照番号が送信された場合、メッセージが返されます.
    ---
    292010x7211
    transaction_logとfailed_transaction_log
    この2つのファイルノードは、最近32回の成功と失敗の伝送記録を提供し、出力情報はほぼ同じである.
    関連するデータ構造はbinder_transaction_log_entry.この構造体はBinder伝送の記述として用いられ,Binder伝送が開始されるたびにdebugのためにグローバル構造体に記録される.
    struct binder_transaction_log_entry {                
        int debug_id; /* transaction log ID */
        int call_type; /*     ,0:call, 1:async, 2:replay */
        int from_proc; /*         PID*/
        int from_thread; /*         PID */
        int target_handle; /* Binder     ,     -1 */
        int to_proc; /*         PID*/
        int to_thread; /*         PID,       0 */
        int to_node; /*      Binder node ID */
        int data_size; /*         */
        int offsets_size; /*          */
    };                
    struct binder_transaction_log {
        int next; /*   log   */
        int full; /*   log     */
        struct binder_transaction_log_entry entry[32]; /*   log   */
    };
    static struct binder_transaction_log binder_transaction_log;
    static struct binder_transaction_log binder_transaction_log_failed;

    Transactions
    Transactionsには、現在のシステム内のすべてのBinderプロセスの転送状態が記録されています.出力例は次のとおりです.
    この出力情報には多くのデータ構造の内容が含まれており、buffer情報とbinder_buffer関連、thread情報とbinder_thread関連、もう一つの最も重要な伝送イベントはbinder_transactionで説明します.
    struct binder_work {
        struct list_head entry; /*        */
        enum {
            BINDER_WORK_TRANSACTION = 1,
            BINDER_WORK_TRANSACTION_COMPLETE,
            BINDER_WORK_NODE,
            BINDER_WORK_DEAD_BINDER,
            BINDER_WORK_DEAD_BINDER_AND_CLEAR,
            BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
        } type;
    };
    ......
    struct binder_transaction {
        int debug_id; /*   ID,     */
        struct binder_work work; /*         */
        struct binder_thread *from; /*         */
        struct binder_transaction *from_parent; /*         */
        struct binder_proc *to_proc; /*         */
        struct binder_thread *to_thread; /*         */
        struct binder_transaction *to_parent; /*         */
        unsigned need_reply:1; /*        */
        /* unsigned is_dead:1; */   /* not used at the moment */
    
        struct binder_buffer *buffer; /*      buffer */
        unsigned int    code; /*        */
        unsigned int    flags; /*     ,  TF_ONE_WAY */
        long    priority; /*       */
        long    saved_priority; /*         */
        kuid_t  sender_euid; /*     uid */
    }