天天看點

android emulator虛拟裝置分析第三篇之pipe上的qemud service一、概述二、guest os中使用qemud service的方法三、注冊新的qemud service

本篇和第二篇是強相關的,需要結合第二篇一起看。

os中的qemud進行相關的,已廢棄。

啟動emulator時,有一個參數-prop <key>=<value>,用于向guest os中添加屬性。

qemud_channel_send和qemud_channel_recv是qemu-pipe和qemud所通用的,直接對fd進行讀寫,先讀寫4個位元組,為size,然後讀取具體的内容。

所有的qemud service都使用pipe:qemud這個pipe service,是它的子服務。如何去實作這種子服務呢?

emulator裡面有兩中結構體QemudService, QemudClient分别表示子服務,以及子服務的client。

QemudPipe和之前說的pipe類似,每次打開/dev/qemu_pipe時,kernel和emulator中都會産生一個pipe,對應一個CHANNEL,在guest os第一次通過/dev/qemu_pipe發送資料時,會建立一個QemudPipe,也就是peer,作為pipe:qemud funcs中的opaque。

pipeConnector_sendBuffers函數代碼片段:

代碼為external/qemu/android/emulation/android_qemud.cpp,我在android源碼中沒有找到,在另一個模拟器的repo中找到了。注意代碼中夾雜着一些guest os中qemud相關的東西,關鍵詞serial,不需要看。

初始化代碼如下,_qemudPipe_funcs就是第二篇中所說的svc->funcs,從第二次通信開始,qemu_pipe都使用這些funcs去讀寫。

_qemudPipe_init是建立連接配接後,初始化QemudPipe的代碼。

QemudMultiplexer中隻有兩個連結清單有用。

先根據service name查找子服務QemudService,然後調用子服務的qemud_service_connect_client去建立QemudClient,然後去建立QemudPipe

_qemudPipe_sendBuffers是guest通過/dev/qemu_pipe寫資料時,将被調用的函數,也就是QemudClient接收到資料的函數,注意不要把send/recv的概念搞錯了。

代碼就是把guest發送的buffers拼起來,然後調用QemudClient的接收函數qemud_client_recv去處理。

_qemudPipe_recvBuffers是guest想從/dev/qemu_pipe讀取資料時被調用的。

QemudClient寫資料時是寫到自己的ProtocolSelector.Pipe.messages中的,在這個函數中把QemudClient中的ProtocolSelector.Pipe.messages倒騰到buffers中。

_qemudPipe_poll,PIPE_POLL_OUT總是有效,PIPE_POLL_IN需要看QemudClient的ProtocolSelector.Pipe.messages中是否有資料

_qemudPipe_wakeOn,發現ProtocolSelector.Pipe.messages中有資料時,會調用android_pipe_wake,把pipe添加到dev->signaled連結清單中。

代碼是external/qemu/android/boot-properties.c,也是在模拟器repo中的

boot_property_init_service去注冊一個QemudService,主要函數就一個boot_property_service_connect,用于建立新的QemudClient

boot_property_service_connect建立新的QemudClient,channel一般都是-1,表示是pipe方式,而不是serial方式(使用guest qemud程序)

qemud_client_new會綁定QemudClient的讀寫函數,讀函數boot_property_client_recv(也就是qemud_client_recv)是在_qemudPipe_sendBuffers中調用的

循環執行qemud_client_send将資料(-prop指定的屬性值的清單)寫到QemudClient的ProtocolSelector.Pipe.messages中,當_qemudPipe_recvBuffers函數執行時,從QemudClient的ProtocolSelector.Pipe.messages中倒騰資料傳回給guest

boot-properties服務的入口函數是boot_property_parse_option,emulator在解析-prop參數時,會調用這個函數。

獲得name和value後,調用boot_property_add2(name, namelen, value, valuelen)去添加屬性到屬性清單(_boot_properties)中

boot_property_add2會檢查服務是否已初始化,如果沒有,将調用boot_property_init_service。如果屬性名和值沒有非法字元,将申請新的屬性:prop = boot_property_alloc(name, namelen, value, valuelen)并添加到屬性清單中

boot_property_init_service先檢查是否已初始化,如果沒有,将進行初始化

QemudService*  serv = qemud_service_register( SERVICE_NAME,

                                                       1, NULL,

                                                       boot_property_service_connect,

                                                       boot_property_save,

                                                       boot_property_load);

第二個參數是max_clients,最大客戶數量

第三個參數是serv_opaque,将傳遞給注冊的serv_connect函數的第一個參數

第四個參數是注冊的serv_connect函數

第五、第六是儲存和恢複屬性連結清單的函數

繼續閱讀