• 第5课第4节_Binder系统_C程序示例_测试与总结


    这个zImage_nfs是通过下面编译出来的

    上机测试:
    a. 烧写非android系统, 比如QT
    b. 重新编译内核让它支持NFS, 更新板上内核

    make menuconfig
    File systems --->
    [*] Network File Systems --->
    <*> NFS client support
    [*] NFS client support for NFS version 3
    [*] NFS client support for the NFSv3 ACL protocol extension
    [*] NFS client support for NFS version 4
    [*] NFS client support for NFSv4.1 (EXPERIMENTAL)
    [*] Root file system on NFS
    [*] Use the legacy NFS DNS resolver
    [*] Use the new idmapper upcall routine

    make zImage

    c. mount nfs, 运行service_manager, test_server, test_client

    mount -t nfs -o nolock 192.168.1.123:/work /mnt
    ./service_manager &
    ./test_server &
    ./test_client hello
    ./test_client hello weidongshan

    git clone https://github.com/weidongshan/APP_0003_Binder_C_App.git

    git checkout v4  // 添加了goodbye服务

    test_client.c

    /* Copyright 2008 The Android Open Source Project
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <linux/types.h>
    #include<stdbool.h>
    #include <string.h>
    
    #include <private/android_filesystem_config.h>
    
    #include "binder.h"
    #include "test_server.h"
    
    
    
    uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
    {
        uint32_t handle;
        unsigned iodata[512/4];
        struct binder_io msg, reply;
    
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
        bio_put_string16_x(&msg, SVC_MGR_NAME);
        bio_put_string16_x(&msg, name);
    
        if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
            return 0;
    
        handle = bio_get_ref(&reply);
    
        if (handle)
            binder_acquire(bs, handle);
    
        binder_done(bs, &msg, &reply);
    
        return handle;
    }
    
    
    struct binder_state *g_bs;
    uint32_t g_hello_handle;
    uint32_t g_goodbye_handle;
    
    void sayhello(void)
    {
        unsigned iodata[512/4];
        struct binder_io msg, reply;
    
        /* 构造binder_io */
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
    
        /* 放入参数 */
    
        /* 调用binder_call */
        if (binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO))
            return ;
        
        /* 从reply中解析出返回值 */
    
        binder_done(g_bs, &msg, &reply);
        
    }
    
    int sayhello_to(char *name)
    {
        unsigned iodata[512/4];
        struct binder_io msg, reply;
        int ret;
    
        /* 构造binder_io */
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
    
        /* 放入参数 */
        bio_put_string16_x(&msg, name);
    
        /* 调用binder_call */
        if (binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO_TO))
            return 0;
        
        /* 从reply中解析出返回值 */
        ret = bio_get_uint32(&reply);
    
        binder_done(g_bs, &msg, &reply);
    
        return ret;
        
    }
    
    
    void saygoodbye(void)
    {
        unsigned iodata[512/4];
        struct binder_io msg, reply;
    
        /* 构造binder_io */
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
    
        /* 放入参数 */
    
        /* 调用binder_call */
        if (binder_call(g_bs, &msg, &reply, g_goodbye_handle, GOODBYE_SVR_CMD_SAYGOODBYE))
            return ;
        
        /* 从reply中解析出返回值 */
    
        binder_done(g_bs, &msg, &reply);
        
    }
    
    int saygoodbye_to(char *name)
    {
        unsigned iodata[512/4];
        struct binder_io msg, reply;
        int ret;
    
        /* 构造binder_io */
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
    
        /* 放入参数 */
        bio_put_string16_x(&msg, name);
    
        /* 调用binder_call */
        if (binder_call(g_bs, &msg, &reply, g_goodbye_handle, GOODBYE_SVR_CMD_SAYGOODBYE_TO))
            return 0;
        
        /* 从reply中解析出返回值 */
        ret = bio_get_uint32(&reply);
    
        binder_done(g_bs, &msg, &reply);
    
        return ret;
        
    }
    
    
    /* ./test_client hello
     * ./test_client hello <name>
     */
    
    int main(int argc, char **argv)
    {
        int fd;
        struct binder_state *bs;
        uint32_t svcmgr = BINDER_SERVICE_MANAGER;
        uint32_t handle;
        int ret;
    
        if (argc < 2){
            fprintf(stderr, "Usage:
    ");
            fprintf(stderr, "%s <hello|goodbye>
    ", argv[0]);
            fprintf(stderr, "%s <hello|goodbye> <name>
    ", argv[0]);
            return -1;
        }
    
        bs = binder_open(128*1024);
        if (!bs) {
            fprintf(stderr, "failed to open binder driver
    ");
            return -1;
        }
        g_bs = bs;
    
    
        /* get service */
        handle = svcmgr_lookup(bs, svcmgr, "goodbye");
        if (!handle) {
            fprintf(stderr, "failed to get goodbye service
    ");
            return -1;
        }
        g_goodbye_handle = handle;
        fprintf(stderr, "Handle for goodbye service = %d
    ", g_goodbye_handle);
    
        handle = svcmgr_lookup(bs, svcmgr, "hello");
        if (!handle) {
            fprintf(stderr, "failed to get hello service
    ");
            return -1;
        }
        g_hello_handle = handle;
        fprintf(stderr, "Handle for hello service = %d
    ", g_hello_handle);
    
        /* send data to server */
        if (!strcmp(argv[1], "hello"))
        {
            if (argc == 2) {
                sayhello();
            } else if (argc == 3) {
                ret = sayhello_to(argv[2]);
                fprintf(stderr, "get ret of sayhello_to = %d
    ", ret);        
            }
        } else if (!strcmp(argv[1], "goodbye"))
        {
            if (argc == 2) {
                saygoodbye();
            } else if (argc == 3) {
                ret = saygoodbye_to(argv[2]);
                fprintf(stderr, "get ret of sayhello_to = %d
    ", ret);        
            }
        }
    
        binder_release(bs, handle);
    
        return 0;
    }

    test_server.c

    /* Copyright 2008 The Android Open Source Project
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <linux/types.h>
    #include<stdbool.h>
    #include <string.h>
    
    #include <private/android_filesystem_config.h>
    
    #include "binder.h"
    #include "test_server.h"
    
    int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
    {
        int status;
        unsigned iodata[512/4];
        struct binder_io msg, reply;
    
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
        bio_put_string16_x(&msg, SVC_MGR_NAME);
        bio_put_string16_x(&msg, name);
        bio_put_obj(&msg, ptr);
    
        if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
            return -1;
    
        status = bio_get_uint32(&reply);
    
        binder_done(bs, &msg, &reply);
    
        return status;
    }
    
    void sayhello(void)
    {
        static int cnt = 0;
        fprintf(stderr, "say hello : %d
    ", cnt++);
    }
    
    
    int sayhello_to(char *name)
    {
        static int cnt = 0;
        fprintf(stderr, "say hello to %s : %d
    ", name, cnt++);
        return cnt;
    }
    
    void saygoodbye(void)
    {
        static int cnt = 0;
        fprintf(stderr, "say goodbye : %d
    ", cnt++);
    }
    
    
    int saygoodbye_to(char *name)
    {
        static int cnt = 0;
        fprintf(stderr, "say goodbye to %s : %d
    ", name, cnt++);
        return cnt;
    }
    
    
    int hello_service_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        /* 根据txn->code知道要调用哪一个函数
         * 如果需要参数, 可以从msg取出
         * 如果要返回结果, 可以把结果放入reply
         */
    
        /* sayhello
         * sayhello_to
         */
        
        uint16_t *s;
        char name[512];
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int i;
    
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
    
    
        switch(txn->code) {
        case HELLO_SVR_CMD_SAYHELLO:
            sayhello();
            return 0;
    
        case HELLO_SVR_CMD_SAYHELLO_TO:
            /* 从msg里取出字符串 */
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            for (i = 0; i < len; i++)
                name[i] = s[i];
            name[i] = '';
    
            /* 处理 */
            i = sayhello_to(name);
    
            /* 把结果放入reply */
            bio_put_uint32(reply, i);
            
            break;
    
        default:
            fprintf(stderr, "unknown code %d
    ", txn->code);
            return -1;
        }
    
        return 0;
    }
    
    
    
    int goodbye_service_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        /* 根据txn->code知道要调用哪一个函数
         * 如果需要参数, 可以从msg取出
         * 如果要返回结果, 可以把结果放入reply
         */
    
        /* sayhello
         * sayhello_to
         */
        
        uint16_t *s;
        char name[512];
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int i;
    
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
    
    
        switch(txn->code) {
        case GOODBYE_SVR_CMD_SAYGOODBYE:
            saygoodbye();
            return 0;
    
        case GOODBYE_SVR_CMD_SAYGOODBYE_TO:
            /* 从msg里取出字符串 */
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            for (i = 0; i < len; i++)
                name[i] = s[i];
            name[i] = '';
    
            /* 处理 */
            i = saygoodbye_to(name);
    
            /* 把结果放入reply */
            bio_put_uint32(reply, i);
            
            break;
    
        default:
            fprintf(stderr, "unknown code %d
    ", txn->code);
            return -1;
        }
    
        return 0;
    }
    
    
    int test_server_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        if (txn->target.ptr == 123)
            return hello_service_handler(bs, txn, msg, reply);
        else if (txn->target.ptr == 124)
            return goodbye_service_handler(bs, txn, msg, reply);
        else
            return -1;
    }
    
    int main(int argc, char **argv)
    {
        int fd;
        struct binder_state *bs;
        uint32_t svcmgr = BINDER_SERVICE_MANAGER;
        uint32_t handle;
        int ret;
    
        bs = binder_open(128*1024);
        if (!bs) {
            fprintf(stderr, "failed to open binder driver
    ");
            return -1;
        }
    
        /* add service */
        ret = svcmgr_publish(bs, svcmgr, "hello", (void *)123);
        if (ret) {
            fprintf(stderr, "failed to publish hello service
    ");
            return -1;
        }
        ret = svcmgr_publish(bs, svcmgr, "goodbye", (void *)124);
        if (ret) {
            fprintf(stderr, "failed to publish goodbye service
    ");
        }
    
    #if 0
        while (1)
        {
            /* read data */
            /* parse data, and process */
            /* reply */
        }
    #endif
        binder_loop(bs, test_server_handler);
    
        return 0;
    }

    test_server.h

    #ifndef _TEST_SERVER_H
    #define _TEST_SERVER_H
    
    #define HELLO_SVR_CMD_SAYHELLO     0
    #define HELLO_SVR_CMD_SAYHELLO_TO  1
    
    #define GOODBYE_SVR_CMD_SAYGOODBYE     0
    #define GOODBYE_SVR_CMD_SAYGOODBYE_TO  1
    
    #endif // _TEST_SERVER_H

    service_manager.c

    /* Copyright 2008 The Android Open Source Project
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <linux/types.h>
    #include<stdbool.h>
    
    #include <private/android_filesystem_config.h>
    
    //#include <selinux/android.h>
    //#include <selinux/avc.h>
    
    #include "binder.h"
    
    #if 1
    #define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
    #define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
    #else
    #define LOG_TAG "ServiceManager"
    #include <cutils/log.h>
    #endif
    
    uint32_t svcmgr_handle;
    
    const char *str8(const uint16_t *x, size_t x_len)
    {
        static char buf[128];
        size_t max = 127;
        char *p = buf;
    
        if (x_len < max) {
            max = x_len;
        }
    
        if (x) {
            while ((max > 0) && (*x != '')) {
                *p++ = *x++;
                max--;
            }
        }
        *p++ = 0;
        return buf;
    }
    
    int str16eq(const uint16_t *a, const char *b)
    {
        while (*a && *b)
            if (*a++ != *b++) return 0;
        if (*a || *b)
            return 0;
        return 1;
    }
    
    static char *service_manager_context;
    
    static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name)
    {
        return true;
    }
    
    static bool check_mac_perms_from_getcon(pid_t spid, const char *perm)
    {
        return true;
    }
    
    static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name)
    {
        return true;
    }
    
    static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
    {
        const char *perm = "add";
        return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
    }
    
    static int svc_can_list(pid_t spid)
    {
        const char *perm = "list";
        return check_mac_perms_from_getcon(spid, perm) ? 1 : 0;
    }
    
    static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid)
    {
        const char *perm = "find";
        return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
    }
    
    struct svcinfo
    {
        struct svcinfo *next;
        uint32_t handle;
        struct binder_death death;
        int allow_isolated;
        size_t len;
        uint16_t name[0];
    };
    
    struct svcinfo *svclist = NULL;
    
    struct svcinfo *find_svc(const uint16_t *s16, size_t len)
    {
        struct svcinfo *si;
    
        for (si = svclist; si; si = si->next) {
            if ((len == si->len) &&
                !memcmp(s16, si->name, len * sizeof(uint16_t))) {
                return si;
            }
        }
        return NULL;
    }
    
    void svcinfo_death(struct binder_state *bs, void *ptr)
    {
        struct svcinfo *si = (struct svcinfo* ) ptr;
    
        ALOGI("service '%s' died
    ", str8(si->name, si->len));
        if (si->handle) {
            binder_release(bs, si->handle);
            si->handle = 0;
        }
    }
    
    uint16_t svcmgr_id[] = {
        'a','n','d','r','o','i','d','.','o','s','.',
        'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
    };
    
    
    uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
    {
        struct svcinfo *si;
    
        if (!svc_can_find(s, len, spid)) {
            ALOGE("find_service('%s') uid=%d - PERMISSION DENIED
    ",
                 str8(s, len), uid);
            return 0;
        }
        si = find_svc(s, len);
        //ALOGI("check_service('%s') handle = %x
    ", str8(s, len), si ? si->handle : 0);
        if (si && si->handle) {
            if (!si->allow_isolated) {
                // If this service doesn't allow access from isolated processes,
                // then check the uid to see if it is isolated.
                uid_t appid = uid % AID_USER;
                if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
                    return 0;
                }
            }
            return si->handle;
        } else {
            return 0;
        }
    }
    
    int do_add_service(struct binder_state *bs,
                       const uint16_t *s, size_t len,
                       uint32_t handle, uid_t uid, int allow_isolated,
                       pid_t spid)
    {
        struct svcinfo *si;
    
        //ALOGI("add_service('%s',%x,%s) uid=%d
    ", str8(s, len), handle,
        //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
    
        if (!handle || (len == 0) || (len > 127))
            return -1;
    
        if (!svc_can_register(s, len, spid)) {
            ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED
    ",
                 str8(s, len), handle, uid);
            return -1;
        }
    
        si = find_svc(s, len);
        if (si) {
            if (si->handle) {
                ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE
    ",
                     str8(s, len), handle, uid);
                svcinfo_death(bs, si);
            }
            si->handle = handle;
        } else {
            si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
            if (!si) {
                ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY
    ",
                     str8(s, len), handle, uid);
                return -1;
            }
            si->handle = handle;
            si->len = len;
            memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
            si->name[len] = '';
            si->death.func = (void*) svcinfo_death;
            si->death.ptr = si;
            si->allow_isolated = allow_isolated;
            si->next = svclist;
            svclist = si;
        }
    
        ALOGI("add_service('%s'), handle = %d
    ", str8(s, len), handle);
    
        binder_acquire(bs, handle);
        binder_link_to_death(bs, handle, &si->death);
        return 0;
    }
    
    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        struct svcinfo *si;
        uint16_t *s;
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int allow_isolated;
    
        //ALOGI("target=%x code=%d pid=%d uid=%d
    ",
        //  txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid);
    
        if (txn->target.handle != svcmgr_handle)
            return -1;
    
        if (txn->code == PING_TRANSACTION)
            return 0;
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
    
        if ((len != (sizeof(svcmgr_id) / 2)) ||
            memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
            fprintf(stderr,"invalid id %s
    ", str8(s, len));
            return -1;
        }
    
    
        switch(txn->code) {
        case SVC_MGR_GET_SERVICE:
        case SVC_MGR_CHECK_SERVICE:
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
            if (!handle)
                break;
            bio_put_ref(reply, handle);
            return 0;
    
        case SVC_MGR_ADD_SERVICE:
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            handle = bio_get_ref(msg);
            allow_isolated = bio_get_uint32(msg) ? 1 : 0;
            if (do_add_service(bs, s, len, handle, txn->sender_euid,
                allow_isolated, txn->sender_pid))
                return -1;
            break;
    
        case SVC_MGR_LIST_SERVICES: {
            uint32_t n = bio_get_uint32(msg);
    
            if (!svc_can_list(txn->sender_pid)) {
                ALOGE("list_service() uid=%d - PERMISSION DENIED
    ",
                        txn->sender_euid);
                return -1;
            }
            si = svclist;
            while ((n-- > 0) && si)
                si = si->next;
            if (si) {
                bio_put_string16(reply, si->name);
                return 0;
            }
            return -1;
        }
        default:
            ALOGE("unknown code %d
    ", txn->code);
            return -1;
        }
    
        bio_put_uint32(reply, 0);
        return 0;
    }
    
    
    
    int main(int argc, char **argv)
    {
        struct binder_state *bs;
    
        bs = binder_open(128*1024);
        if (!bs) {
            ALOGE("failed to open binder driver
    ");
            return -1;
        }
    
        if (binder_become_context_manager(bs)) {
            ALOGE("cannot become context manager (%s)
    ", strerror(errno));
            return -1;
        }
    
    
        svcmgr_handle = BINDER_SERVICE_MANAGER;
        binder_loop(bs, svcmgr_handler);
    
        return 0;
    }

    git checkout v5  // 改进

    test_server.c  只修改了这个文件

    /* Copyright 2008 The Android Open Source Project
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <linux/types.h>
    #include<stdbool.h>
    #include <string.h>
    
    #include <private/android_filesystem_config.h>
    
    #include "binder.h"
    #include "test_server.h"
    
    int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
    {
        int status;
        unsigned iodata[512/4];
        struct binder_io msg, reply;
    
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
        bio_put_string16_x(&msg, SVC_MGR_NAME);
        bio_put_string16_x(&msg, name);
        bio_put_obj(&msg, ptr);
    
        if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
            return -1;
    
        status = bio_get_uint32(&reply);
    
        binder_done(bs, &msg, &reply);
    
        return status;
    }
    
    void sayhello(void)
    {
        static int cnt = 0;
        fprintf(stderr, "say hello : %d
    ", cnt++);
    }
    
    
    int sayhello_to(char *name)
    {
        static int cnt = 0;
        fprintf(stderr, "say hello to %s : %d
    ", name, cnt++);
        return cnt;
    }
    
    void saygoodbye(void)
    {
        static int cnt = 0;
        fprintf(stderr, "say goodbye : %d
    ", cnt++);
    }
    
    
    int saygoodbye_to(char *name)
    {
        static int cnt = 0;
        fprintf(stderr, "say goodbye to %s : %d
    ", name, cnt++);
        return cnt;
    }
    
    
    int hello_service_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        /* 根据txn->code知道要调用哪一个函数
         * 如果需要参数, 可以从msg取出
         * 如果要返回结果, 可以把结果放入reply
         */
    
        /* sayhello
         * sayhello_to
         */
        
        uint16_t *s;
        char name[512];
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int i;
    
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
    
    
        switch(txn->code) {
        case HELLO_SVR_CMD_SAYHELLO:
            sayhello();
            return 0;
    
        case HELLO_SVR_CMD_SAYHELLO_TO:
            /* 从msg里取出字符串 */
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            for (i = 0; i < len; i++)
                name[i] = s[i];
            name[i] = '';
    
            /* 处理 */
            i = sayhello_to(name);
    
            /* 把结果放入reply */
            bio_put_uint32(reply, i);
            
            break;
    
        default:
            fprintf(stderr, "unknown code %d
    ", txn->code);
            return -1;
        }
    
        return 0;
    }
    
    
    
    int goodbye_service_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        /* 根据txn->code知道要调用哪一个函数
         * 如果需要参数, 可以从msg取出
         * 如果要返回结果, 可以把结果放入reply
         */
    
        /* sayhello
         * sayhello_to
         */
        
        uint16_t *s;
        char name[512];
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int i;
    
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
    
    
        switch(txn->code) {
        case GOODBYE_SVR_CMD_SAYGOODBYE:
            saygoodbye();
            return 0;
    
        case GOODBYE_SVR_CMD_SAYGOODBYE_TO:
            /* 从msg里取出字符串 */
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            for (i = 0; i < len; i++)
                name[i] = s[i];
            name[i] = '';
    
            /* 处理 */
            i = saygoodbye_to(name);
    
            /* 把结果放入reply */
            bio_put_uint32(reply, i);
            
            break;
    
        default:
            fprintf(stderr, "unknown code %d
    ", txn->code);
            return -1;
        }
    
        return 0;
    }
    
    
    int test_server_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        int (*handler)(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply);
    
        handler = (int (*)(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply))txn->target.ptr;   //进行了数据类型转换 handler = txn->target.ptr
        
        return handler(bs, txn, msg, reply);
    }
    
    int main(int argc, char **argv)
    {
        int fd;
        struct binder_state *bs;
        uint32_t svcmgr = BINDER_SERVICE_MANAGER;
        uint32_t handle;
        int ret;
    
        bs = binder_open(128*1024);
        if (!bs) {
            fprintf(stderr, "failed to open binder driver
    ");
            return -1;
        }
    
        /* add service */
        ret = svcmgr_publish(bs, svcmgr, "hello", hello_service_handler);
        if (ret) {
            fprintf(stderr, "failed to publish hello service
    ");
            return -1;
        }
        ret = svcmgr_publish(bs, svcmgr, "goodbye", goodbye_service_handler);
        if (ret) {
            fprintf(stderr, "failed to publish goodbye service
    ");
        }
    
    #if 0
        while (1)
        {
            /* read data */
            /* parse data, and process */
            /* reply */
        }
    #endif
        binder_loop(bs, test_server_handler);
    
        return 0;
    }
  • 相关阅读:
    Nginx负载均衡配置
    云鹏在美团八年工作总结
    尽量不要让儿女从事这3种工作,钱再多也别做,坚持再久也没前途
    Nginx 配置ip_hash
    postgresql获取表结构,表名、表注释、字段名、字段类型及长度和字段注释
    更快的Maven来了,我的天,速度提升了8倍!
    Nginx负载均衡配置及算法详解
    nginx负载均衡策略:ip_hash、url_hash
    Windows Phone实用开发技巧(41):解决WebBrowser中显示黑色背景网页闪屏
    Windows Phone实用开发技巧(32):照片角度处理
  • 原文地址:https://www.cnblogs.com/zhulinhaibao/p/7073555.html
Copyright © 2020-2023  润新知