Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發環境 >> Android開發工具ADB教程之三:Dalvik虛擬機之jdwp線程

Android開發工具ADB教程之三:Dalvik虛擬機之jdwp線程

編輯:Android開發環境

       jdwp(java debug wire protocol)是dalvik VM的一個線程,可以建立在adb或者tcp基礎上,與DDMS或debugger進行通信。

       代碼位置:

       dalvik/vm/jdwp

       frameworks/base/core/jni


       java虛擬機初始化後,或者每次“zygote fork”出一個新進程時,會啟動jdwp線程。

       主要調用路徑:dvmStartup->dvmInitAfterZygote->dvmInitJDWP。

       dvmInitJDWP線程啟動之前會可能會阻塞VM,依賴於配置suspend=n,所以dvmInitJDWP放在dvmStartup的最後步驟來執行。

       dvmInitJDWP首先判斷jdwp是否允許並且已經配置好,如果是,則讀取jdwp的配置,這些配置是AndroidRuntime::startVm中配置的。

C++代碼
  1.     /* enable debugging; set suspend=y to pause during VM init */  
  2. #ifdef HAVE_ANDROID_OS   
  3.     /* use android ADB transport */  
  4.     opt.optionString =   
  5.         "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";   
  6. #else   
  7.     /* use TCP socket; address=0 means start at port 8000 and probe up */  
  8.     LOGI("Using TCP socket for JDWP\n");   
  9.     opt.optionString =   
  10.         "-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";   
  11. #endif  

       這些配置保存在虛擬機全局變量gDvm中,gDvm是DvmGlobals變量,需要讀取的配置包括transport,負責與ADB或TCP交換數據。

C++代碼
  1. if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {   
  2.     JdwpStartupParams params;   
  3.   
  4.   
  5.     if (gDvm.jdwpHost != NULL) {   
  6.         if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {   
  7.             LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);   
  8.             return false;   
  9.         }   
  10.         strcpy(params.host, gDvm.jdwpHost);   
  11.     } else {   
  12.         params.host[0] = '\0';   
  13.     }   
  14.     params.transport = gDvm.jdwpTransport;   
  15.     params.server = gDvm.jdwpServer;   
  16.     params.suspend = gDvm.jdwpSuspend;   
  17.     params.port = gDvm.jdwpPort;   
  18.   
  19.   
  20.     gDvm.jdwpState = dvmJdwpStartup(¶ms);   
  21.     if (gDvm.jdwpState == NULL) {   
  22.         LOGW("WARNING: debugger thread failed to initialize\n");   
  23.         /* TODO: ignore? fail? need to mimic "expected" behavior */  
  24.     }   
  25. }  

       其中gDvm.jdwpAllowed在dalvik_system_Zygote.c中配置:

       gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);

       gDvm.jdwpConfigured在調用dvmStartup->dvmProcessOptions->parseJdwpOptions時配置。

       參考上面的參數,對照Init.c的handleJdwpOption的函數,可知gDvm.jdwpTransport為kJdwpTransportAndroidAdb,gDvm.jdwpServer為true,gDvm.jdwpSuspend為false,gDvm.jdwpPort沒有配置,這些參數保存到dvmJdwpStartup的參數裡面。

       再看dvmJdwpStartup,在裡面,創建jdwp相關的結構體JdwpState,是先初始化一些互斥鎖和條件鎖,初始化transport。

C++代碼
  1. switch (pParams->transport) {   
  2. case kJdwpTransportSocket:   
  3.     // LOGD("prepping for JDWP over TCP\n");   
  4.     state->transport = dvmJdwpSocketTransport();   
  5.     break;   
  6. case kJdwpTransportAndroidAdb:   
  7.     // LOGD("prepping for JDWP over ADB\n");   
  8.     state->transport = dvmJdwpAndroidAdbTransport();   
  9.     /* TODO */  
  10.     break;   
  11. default:   
  12.     LOGE("Unknown transport %d\n", pParams->transport);   
  13.     assert(false);   
  14.     goto fail;   
  15. }  

       由上文可知,這裡執行dvmJdwpAndroidAdbTransport,返回一個JdwpTransport的接口指針結構體,這些在ADB和TCP上各有一套實現方法,對應不同類型的transport。

C++代碼
  1. typedef struct JdwpTransport {   
  2.     bool (*startup)(struct JdwpState* state, const JdwpStartupParams* pParams);   
  3.     bool (*accept)(struct JdwpState* state);   
  4.     bool (*establish)(struct JdwpState* state);   
  5.     void (*close)(struct JdwpState* state);   
  6.     void (*shutdown)(struct JdwpState* state);   
  7.     void (*free)(struct JdwpState* state);   
  8.     bool (*isConnected)(struct JdwpState* state);   
  9.     bool (*awaitingHandshake)(struct JdwpState* state);   
  10.     bool (*processIncoming)(struct JdwpState* state);   
  11.     bool (*sendRequest)(struct JdwpState* state, ExpandBuf* pReq);   
  12.     bool (*sendBufferedRequest)(struct JdwpState* state,   
  13.         const struct iovec* iov, int iovcnt);   
  14. } JdwpTransport;  

       然後,調用dvmJdwpNetStartup,在裡面實際執行JdwpTransport在ADB上的startup接口。在JdwpADB.c的start函數內,初始化與adb有關的一些網絡參數,比如socket名稱。

C++代碼
  1. #define kJdwpControlName    "\0jdwp-control"    

       這個socket名稱已經被adbd綁定。

       然後,調用dvmCreateInternalThread啟動jdwp線程,dvmCreateInternalThread是pthread_create的包裝,最終線程的執行函數是jdwpThreadStart。

       在jdwpThreadStart中,會調用dvmJdwpEstablishConnection與adbd建立連接。在dvmJdwpEstablishConnection中,會一直等待與adbd的連接,直到連接成功。

C++代碼
  1. int  ret = connect(netState->controlSock,                            
  2.                    &netState->controlAddr.controlAddrPlain,          
  3.                    netState->controlAddrLen);             

       如果執行connect成功,則將pid發送給adbd。

C++代碼
  1. snprintf(buff, sizeof(buff), "%04x", getpid());   
  2. buff[4] = 0;   
  3.         do {                                                             
  4.             ret = send( netState->controlSock, buff, 4, 0 );             
  5.         } while (ret < 0 && errno == EINTR);       

       接著,jdwp等待adbd返回一個客戶文件描述符。

C++代碼
  1. netState->clientSock = receiveClientFd(netState);  

       如果返回成功,這個clientSock將用來直接與debugger或DDMS通信。可以想象,這裡的clientSock就是TCP:5037對應的client描述符。

       這樣acceptConnection也成功返回了,回到jdwp線程處理函數jdwpThreadStart,接著進入一個while循環從adbd讀取並處理握手消息。

C++代碼
  1. while (true) {   
  2.     // sanity check -- shouldn't happen?   
  3.     if (dvmThreadSelf()->status != THREAD_VMWAIT) {   
  4.         LOGE("JDWP thread no longer in VMWAIT (now %d); resetting\n",   
  5.             dvmThreadSelf()->status);   
  6.         dvmDbgThreadWaiting();   
  7.     }   
  8.   
  9.   
  10.     if (!dvmJdwpProcessIncoming(state))     /* blocking read */  
  11.         break;   
  12.   
  13.   
  14.     if (first && !dvmJdwpAwaitingHandshake(state)) {   
  15.         /* handshake worked, tell the interpreter that we're active */  
  16.         first = false;   
  17.   
  18.   
  19.         /* set thread ID; requires object registry to be active */  
  20.         state->debugThreadId = dvmDbgGetThreadSelfId();   
  21.   
  22.   
  23.         /* wake anybody who's waiting for us */  
  24.         dvmDbgLockMutex(&state->attachLock);   
  25.         dvmDbgCondBroadcast(&state->attachCond);   
  26.         dvmDbgUnlockMutex(&state->attachLock);   
  27.     }   
  28. }  

       先看dvmJdwpProcessIncoming函數,在裡面執行select,可能會收到三種數據,對應三個文件描述被set,其中wakeFds是定時喚醒作用,丟棄,controlSock的set也忽略,因為不需要接收第二個debugger文件描述服。

       之後收到debugger的數據,也就是clientSock被set的時候調用read讀取數據,如果不是一個單位數據包長度,則dvmJdwpProcessIncoming返回。否則,調用handlePacket處理數據包:handlePacket->dvmJdwpProcessRequest->write。handlePacket將包中的數據還原成JdwpReqHeader和數據起始指針,送給dvmJdwpProcessRequest處理,dvmJdwpProcessRequest從gHandlerMap調出處理函數func。

C++代碼
  1. typedef struct {                                                                 
  2.     u1  cmdSet;                                                                  
  3.     u1  cmd;   
  4.     JdwpRequestHandler  func;                                                    
  5.     const char* descr;                                                           
  6. } JdwpHandlerMap;    

       write將結果寫回給adbd,adbd處理之後在發回給HOST端。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved