[026]Zygote中Socket通信能否替換成Binder通信?

首先聲明一下這是一個(gè)討論帖,我只是論述一下個(gè)人的觀點(diǎn),歡迎大家講事實(shí)擺道理。

前言

大家都知道App進(jìn)程是AMS通過通過Socket通信通知Zygote孵化出來的,借用gityuan的圖就是圖中的第2步,能否用Binder通信替換Socket通信?我們只討論技術(shù)上實(shí)現(xiàn)的可能性,不討論兩者性能上的差異。


我的觀點(diǎn)

能替換成Binder通信。

我的論據(jù)

我實(shí)在是想不出用Binder通信替換Socket通信的缺陷在哪里?

別人觀點(diǎn)

既然我想不出,肯定網(wǎng)上有人持否定態(tài)度,我們看看他們說的有沒有道理。

觀點(diǎn)1:并發(fā)問題

鏈接:

https://blog.csdn.net/qq_39037047/article/details/88066589

觀點(diǎn)描述:

怕父進(jìn)程binder線程有鎖,然后子進(jìn)程的主線程一直在等其子線程(從父進(jìn)程拷貝過來的子進(jìn)程)的資源,但是其實(shí)父進(jìn)程的子進(jìn)程并沒有被拷貝過來,造成死鎖,所以fork不允許存在多線程。而非常巧的是Binder通訊偏偏就是多線程,所以干脆父進(jìn)程(Zygote)這個(gè)時(shí)候就不使用binder線程

反駁:

我們完全可以將Zygote進(jìn)程的主線程作為唯一的Binder線程,這樣子也就沒有這個(gè)問題了。

觀點(diǎn)2:父子進(jìn)程共享FD問題(其實(shí)這個(gè)是我以前早期的觀點(diǎn))

觀點(diǎn)描述:

因?yàn)閆ygote在open("dev/binder")中帶有的flag是O_CLOEXEC,fork之后,在子進(jìn)程執(zhí)行EXEC的時(shí)候,會(huì)因?yàn)镺_CLOEXEC的條件關(guān)閉這個(gè)共享FD,就會(huì)調(diào)用binder_release的代碼,順帶清空父進(jìn)程的FD對(duì)應(yīng)file結(jié)構(gòu)體中private_data對(duì)象保存的binder_proc,影響父進(jìn)程的Binder通信功能。

/frameworks/native/libs/binder/ProcessState.cpp
static int open_driver(const char *driver)
{
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    return fd;
}

drivers/staging/android/binder.c
static int binder_release(struct inode *nodp, struct file *filp)
{
    struct binder_proc *proc = filp->private_data;
    debugfs_remove(proc->debugfs_entry);
    binder_defer_work(proc, BINDER_DEFERRED_RELEASE);//調(diào)用到代碼1.1
    return 0;
}

//1.1
binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
{
    mutex_lock(&binder_deferred_lock);
    proc->deferred_work |= defer;
    if (hlist_unhashed(&proc->deferred_work_node)) {
        hlist_add_head(&proc->deferred_work_node,
                &binder_deferred_list);
        //發(fā)起一個(gè)workqueue去執(zhí)行binder_deferred_work,也就是代碼1.2
        queue_work(binder_deferred_workqueue, &binder_deferred_work);
    }
    mutex_unlock(&binder_deferred_lock);
}

//1.2
static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
static void binder_deferred_func(struct work_struct *work)
{
    ...
    do {
        ...
        if (defer & BINDER_DEFERRED_RELEASE)
            binder_deferred_release(proc); /* frees proc */ //代碼1.3
                ...
    } while (proc);
}

//1.3
static void binder_deferred_release(struct binder_proc *proc)
{
    ...
    kfree(proc);//這里會(huì)釋放父進(jìn)程的binder_proc
}

反駁:

鏈接:https://blog.csdn.net/scarecrow_byr/article/details/91410131

上述的觀點(diǎn)對(duì)O_CLOEXEC的理解有些偏差,正確的理解應(yīng)該是在linux系統(tǒng)中,父進(jìn)程打開一個(gè)文件fd可以帶上O_CLOEXEC標(biāo)志位,fork之后,子進(jìn)程得到父進(jìn)程的完整拷貝,對(duì)于父進(jìn)程已經(jīng)open的文件,子進(jìn)程也可以得到一樣的fd。內(nèi)核里,子進(jìn)程只是把fd對(duì)應(yīng)的file指針指向父進(jìn)程fd對(duì)應(yīng)的struct file,并且把file的引用加1。子進(jìn)程中用exec系列系統(tǒng)調(diào)用加載新的可執(zhí)行程序之前,會(huì)關(guān)閉子進(jìn)程中父進(jìn)程O_CLOEXEC標(biāo)志打開的fd。子進(jìn)程關(guān)閉該fd時(shí)候,但是因?yàn)楦高M(jìn)程還持有fd的引用計(jì)數(shù),所以這個(gè)關(guān)閉的動(dòng)作只會(huì)執(zhí)行fops的flush回調(diào)函數(shù),并沒有真正調(diào)用fops的release回調(diào)函數(shù)。

看Binder驅(qū)動(dòng)中實(shí)現(xiàn)的flush回調(diào)函數(shù)binder_flush,最后調(diào)用的binder_deferred_flush方法中,并沒有釋放binder_proc,只是喚醒一下父進(jìn)程的Binder線程而已。

static void binder_deferred_flush(struct binder_proc *proc)
{
    struct rb_node *n;
    int wake_count = 0;

    for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
        struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);

        thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
        if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
            wake_up_interruptible(&thread->wait);
            wake_count++;
        }
    }
    wake_up_interruptible_all(&proc->wait);

    binder_debug(BINDER_DEBUG_OPEN_CLOSE,
             "binder_flush: %d woke %d threads\n", proc->pid,
             wake_count);
}

總結(jié)

以上就是我覺得看似合理的兩個(gè)觀點(diǎn)的反駁,如果你們有新的觀點(diǎn),或者覺得我的反駁中的論據(jù)有問題。

歡迎留言交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容