摘要:抱歉,此文暫時作廢,不會使用的刪除功能。我會在后面重新整理后再繼續(xù)寫下去。是內(nèi)部的一個機(jī)制,通過設(shè)備驅(qū)動的協(xié)助能夠起到進(jìn)程間通訊的的作用。這個應(yīng)該是個全局表,統(tǒng)計所有結(jié)構(gòu)。實際上是保存在打開的設(shè)備文件的結(jié)構(gòu)中。目前還未涉及到其他操作,只是。
抱歉,此文暫時作廢,不會使用segmentfault的刪除功能。我會在后面重新整理后再繼續(xù)寫下去。
繼續(xù)上篇的文,這篇打算進(jìn)入到android的內(nèi)核世界,真正接觸到binder。
binder是android內(nèi)部的一個機(jī)制,通過設(shè)備驅(qū)動的協(xié)助能夠起到進(jìn)程間通訊的(ipc)的作用。那么binder的設(shè)備驅(qū)動的源碼在/drivers/staging/android/binder.c這個路徑下。
先看下定義:
3632static const struct file_operations binder_fops = { 3633 .owner = THIS_MODULE, 3634 .poll = binder_poll, 3635 .unlocked_ioctl = binder_ioctl, 3636 .compat_ioctl = binder_ioctl, 3637 .mmap = binder_mmap, 3638 .open = binder_open, 3639 .flush = binder_flush, 3640 .release = binder_release, 3641};
這里說明了設(shè)備的各項操作對應(yīng)的函數(shù)。
設(shè)備驅(qū)動是在系統(tǒng)剛開始的時候就初始化好的,初始化的過程看binder_init,不是重點,因此不在這里累述。這個初始化的過程如果進(jìn)入的以及怎么發(fā)展的,有機(jī)會再其他文中敘述吧。
上文的servicemanager的main函數(shù)中首先就是open設(shè)備,因此先從open開始:
2941static int binder_open(struct inode *nodp, struct file *filp) 2942{ 2943 struct binder_proc *proc; 2944 2945 binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d ", 2946 current->group_leader->pid, current->pid); 2947 2948 proc = kzalloc(sizeof(*proc), GFP_KERNEL); 2949 if (proc == NULL) 2950 return -ENOMEM; 2951 get_task_struct(current); 2952 proc->tsk = current; 2953 INIT_LIST_HEAD(&proc->todo); 2954 init_waitqueue_head(&proc->wait); 2955 proc->default_priority = task_nice(current); 2956 2957 binder_lock(__func__); 2958 2959 binder_stats_created(BINDER_STAT_PROC); 2960 hlist_add_head(&proc->proc_node, &binder_procs); 2961 proc->pid = current->group_leader->pid; 2962 INIT_LIST_HEAD(&proc->delivered_death); 2963 filp->private_data = proc; 2964 2965 binder_unlock(__func__); 2966 2967 if (binder_debugfs_dir_entry_proc) { 2968 char strbuf[11]; 2969 2970 snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); 2971 proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO, 2972 binder_debugfs_dir_entry_proc, proc, &binder_proc_fops); 2973 } 2974 2975 return 0; 2976}
1.創(chuàng)建binder_proc結(jié)構(gòu);
2.各種維護(hù)性的鏈表及結(jié)構(gòu)的添加;
3.存儲proc到私有數(shù)據(jù)內(nèi);
先說下,內(nèi)核開空間都是使用kzalloc與應(yīng)用層的malloc類似。
這里用到一個current結(jié)構(gòu),是linux的一個指針,指向當(dāng)前正在運行的進(jìn)程結(jié)構(gòu)task_struct,這里還是先不深究,大體意思了解不影響后續(xù)即可。后面就是INIT_LIST_HEAD(&proc->todo);初始化鏈表頭,這個鏈表是怎么回事兒呢?先看下proc的結(jié)構(gòu)吧:
292struct binder_proc { 293 struct hlist_node proc_node; 294 struct rb_root threads; 295 struct rb_root nodes; 296 struct rb_root refs_by_desc; 297 struct rb_root refs_by_node; 298 int pid; 299 struct vm_area_struct *vma; 300 struct mm_struct *vma_vm_mm; 301 struct task_struct *tsk; 302 struct files_struct *files; 303 struct hlist_node deferred_work_node; 304 int deferred_work; 305 void *buffer; 306 ptrdiff_t user_buffer_offset; 307 308 struct list_head buffers; 309 struct rb_root free_buffers; 310 struct rb_root allocated_buffers; 311 size_t free_async_space; 312 313 struct page **pages; 314 size_t buffer_size; 315 uint32_t buffer_free; 316 struct list_head todo; 317 wait_queue_head_t wait; 318 struct binder_stats stats; 319 struct list_head delivered_death; 320 int max_threads; 321 int requested_threads; 322 int requested_threads_started; 323 int ready_threads; 324 long default_priority; 325 struct dentry *debugfs_entry; 326};
這個結(jié)構(gòu)的寫法很c很linux,可以看到可能會有很多個proc結(jié)構(gòu)被貫穿成為一個鏈表統(tǒng)一管理,那么結(jié)合之前的內(nèi)容猜測,binder_proc結(jié)構(gòu)可以支持多個每個對應(yīng)一個進(jìn)程,然后通過鏈表來維護(hù),那么進(jìn)一步思考,本身binder就是為了支持跨進(jìn)程通訊的,那么這些通訊之間的binder銜接就是在這個鏈表結(jié)構(gòu)中維護(hù)。
下面,init_waitqueue_head(&proc->wait);初始化linux的等待隊列。又是個宏,內(nèi)容如下:
71#define init_waitqueue_head(q) 72 do { 73 static struct lock_class_key __key; 74 75 __init_waitqueue_head((q), #q, &__key); 76 } while (0) 77 78#ifdef CONFIG_LOCKDEP 79# define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) 80 ({ init_waitqueue_head(&name); name; }) 81# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) 82 wait_queue_head_t name = __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) 83#else 84# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name) 85#endif 86
帶入的參數(shù)是proc結(jié)構(gòu)中的一個成員wait,感覺這里也是個隊列(鏈表),用來維護(hù)等待處理的binder_proc結(jié)構(gòu)。那么大膽猜測下,系統(tǒng)利用這個來建立等待通訊處理的binder進(jìn)程隊列,可在這基礎(chǔ)上進(jìn)行各種策略調(diào)配來管理binder通訊的過程,不能放著驅(qū)動自我的承載力來決定(可能帶來穩(wěn)定性隱患)。
再往后看,proc->default_priority = task_nice(current); 記錄當(dāng)前進(jìn)程的優(yōu)先級??窗?,之前的策略這里就會體現(xiàn)。
然后hlist_add_head(&proc->proc_node, &binder_procs);又一個,真linux真c,不得不說:看系統(tǒng)源碼就必須習(xí)慣各種鏈表的這種方式,其實很好,不用額外維護(hù)什么東西,這種原始的方式其實有時候是最適合的,所以說,機(jī)制不是多復(fù)雜就牛逼的,而是看是否符合當(dāng)前的體系當(dāng)前的場景。這個應(yīng)該是個全局hash表,統(tǒng)計所有binder_proc結(jié)構(gòu)。
借用一張網(wǎng)絡(luò)上的圖說明下proc結(jié)構(gòu):
最后保存這個proc倒private_data里,這個私有數(shù)據(jù)中。然后完了。
再回顧一下吧,每次打開設(shè)備就創(chuàng)建一個binder_proc結(jié)構(gòu),并將當(dāng)前進(jìn)程的信息保存在這里,然后將其掛接在系統(tǒng)的各個鏈表或紅黑樹或hash表中,為了便于日后的策略和維護(hù)。之后再將這個proc結(jié)構(gòu)保留到私有數(shù)據(jù)中。實際上是保存在打開的設(shè)備文件的結(jié)構(gòu)中。目前還未涉及到其他操作,只是binder_open。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65002.html
摘要:以版本源碼為例。源碼位于下打開驅(qū)動設(shè)備,將自己作為的管理者,進(jìn)入循環(huán),作為等待的請求位于首先,建立一個結(jié)構(gòu)體,然后剩下的就是給這個結(jié)構(gòu)體的成員賦值。同屬于這一層,因此我們看看具體內(nèi)容剛才從驅(qū)動設(shè)備讀取的的前位取出來作為進(jìn)行判斷處理。 前一陣子在忙項目,沒什么更新,這次開始寫點android源碼內(nèi)部的東西分析下。以6.0.1_r10版本android源碼為例。servicemanager...
摘要:也同時可以看到責(zé)任鏈的應(yīng)用,一個請求從上到下會經(jīng)過很多層,每層都只處理和自己相關(guān)的部分,如果沒有則交由下層繼續(xù)傳遞,如果有直接返回。因此雖然看著費勁點,但是在此還是要對搞操作系統(tǒng)的以及研究操作系統(tǒng)的人們給予敬意。 承接上篇,serviceManager是怎么被調(diào)用的呢?如何為app提供服務(wù)支持?怎么銜接的?。這次我打算從最上層開始逐步把脈絡(luò)屢清楚。首先,我們在寫app的時候需要使用Au...
摘要:的構(gòu)造傳遞進(jìn)入的就是。如果狀態(tài)是,直接返回。到底是否正確呢看代碼先創(chuàng)建一個對象,這個對象是個存儲讀寫內(nèi)容的對象。然后終于進(jìn)入了內(nèi)核驅(qū)動的部分。 承接上文,從getService開始,要開始走binder的通訊機(jī)制了。首先是上文的java層 /frameworks/base/core/java/android/os/ServiceManagerNative.java: 118 pu...
閱讀 2512·2021-10-14 09:42
閱讀 1150·2021-09-22 15:09
閱讀 3556·2021-09-09 09:33
閱讀 3037·2021-09-07 09:59
閱讀 3652·2021-09-03 10:34
閱讀 3555·2021-07-26 22:01
閱讀 2836·2019-08-30 13:06
閱讀 1217·2019-08-30 10:48