首先聲明一下這是一個討論帖江滨,我只是論述一下個人的觀點铛纬,歡迎大家講事實擺道理。
前言
大家都知道App進程是AMS通過通過Socket通信通知Zygote孵化出來的唬滑,借用gityuan的圖就是圖中的第2步告唆,能否用Binder通信替換Socket通信?我們只討論技術(shù)上實現(xiàn)的可能性晶密,不討論兩者性能上的差異擒悬。
我的觀點
能替換成Binder通信。
我的論據(jù)
我實在是想不出用Binder通信替換Socket通信的缺陷在哪里稻艰?
別人觀點
既然我想不出懂牧,肯定網(wǎng)上有人持否定態(tài)度,我們看看他們說的有沒有道理尊勿。
觀點1:并發(fā)問題
鏈接:
https://blog.csdn.net/qq_39037047/article/details/88066589
觀點描述:
怕父進程binder線程有鎖僧凤,然后子進程的主線程一直在等其子線程(從父進程拷貝過來的子進程)的資源,但是其實父進程的子進程并沒有被拷貝過來元扔,造成死鎖拼弃,所以fork不允許存在多線程。而非常巧的是Binder通訊偏偏就是多線程摇展,所以干脆父進程(Zygote)這個時候就不使用binder線程
反駁:
我們完全可以將Zygote進程的主線程作為唯一的Binder線程吻氧,這樣子也就沒有這個問題了。
觀點2:父子進程共享FD問題(其實這個是我以前早期的觀點)
觀點描述:
因為Zygote在open("dev/binder")中帶有的flag是O_CLOEXEC咏连,fork之后盯孙,在子進程執(zhí)行EXEC的時候,會因為O_CLOEXEC的條件關(guān)閉這個共享FD祟滴,就會調(diào)用binder_release的代碼振惰,順帶清空父進程的FD對應(yīng)file結(jié)構(gòu)體中private_data對象保存的binder_proc,影響父進程的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ā)起一個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);//這里會釋放父進程的binder_proc
}
反駁:
鏈接:https://blog.csdn.net/scarecrow_byr/article/details/91410131
上述的觀點對O_CLOEXEC的理解有些偏差痛垛,正確的理解應(yīng)該是在linux系統(tǒng)中,父進程打開一個文件fd可以帶上O_CLOEXEC標志位桶蛔,fork之后匙头,子進程得到父進程的完整拷貝,對于父進程已經(jīng)open的文件仔雷,子進程也可以得到一樣的fd蹂析。內(nèi)核里,子進程只是把fd對應(yīng)的file指針指向父進程fd對應(yīng)的struct file碟婆,并且把file的引用加1电抚。子進程中用exec系列系統(tǒng)調(diào)用加載新的可執(zhí)行程序之前,會關(guān)閉子進程中父進程O_CLOEXEC標志打開的fd竖共。子進程關(guān)閉該fd時候蝙叛,但是因為父進程還持有fd的引用計數(shù),所以這個關(guān)閉的動作只會執(zhí)行fops的flush回調(diào)函數(shù)公给,并沒有真正調(diào)用fops的release回調(diào)函數(shù)借帘。
看Binder驅(qū)動中實現(xiàn)的flush回調(diào)函數(shù)binder_flush,最后調(diào)用的binder_deferred_flush方法中妓布,并沒有釋放binder_proc姻蚓,只是喚醒一下父進程的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é)
以上就是我覺得看似合理的兩個觀點的反駁匣沼,如果你們有新的觀點,或者覺得我的反駁中的論據(jù)有問題捂龄。
歡迎留言交流释涛。