<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 101,  comments - 29,  trackbacks - 0

            Android應(yīng)用程序框架層創(chuàng)建的應(yīng)用程序進(jìn)程具有兩個(gè)特點(diǎn),一是進(jìn)程的入口函數(shù)是ActivityThread.main,二是進(jìn)程天然支持Binder進(jìn)程間通信機(jī)制;這兩個(gè)特點(diǎn)都是在進(jìn)程的初始化過(guò)程中實(shí)現(xiàn)的,本文將詳細(xì)分析Android應(yīng)用程序進(jìn)程創(chuàng)建過(guò)程中是如何實(shí)現(xiàn)這兩個(gè)特點(diǎn)的。

            Android應(yīng)用程序框架層創(chuàng)建的應(yīng)用程序進(jìn)程的入口函數(shù)是ActivityThread.main比較好理解,即進(jìn)程創(chuàng)建完成之后,Android應(yīng)用程序框架層就會(huì)在這個(gè)進(jìn)程中將ActivityThread類加載進(jìn)來(lái),然后執(zhí)行它的main函數(shù),這個(gè)main函數(shù)就是進(jìn)程執(zhí)行消息循環(huán)的地方了。Android應(yīng)用程序框架層創(chuàng)建的應(yīng)用程序進(jìn)程天然支持Binder進(jìn)程間通信機(jī)制這個(gè)特點(diǎn)應(yīng)該怎么樣理解呢?前面我們?cè)趯W(xué)習(xí)Android系統(tǒng)的Binder進(jìn)程間通信機(jī)制時(shí)說(shuō)到,它具有四個(gè)組件,分別是驅(qū)動(dòng)程序、守護(hù)進(jìn)程、Client以及Server,其中Server組件在初始化時(shí)必須進(jìn)入一個(gè)循環(huán)中不斷地與Binder驅(qū)動(dòng)程序進(jìn)行到交互,以便獲得Client組件發(fā)送的請(qǐng)求,具體可參考Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server啟動(dòng)過(guò)程源代碼分析一文,但是,當(dāng)我們?cè)贏ndroid應(yīng)用程序中實(shí)現(xiàn)Server組件的時(shí)候,我們并沒(méi)有讓進(jìn)程進(jìn)入一個(gè)循環(huán)中去等待Client組件的請(qǐng)求,然而,當(dāng)Client組件得到這個(gè)Server組件的遠(yuǎn)程接口時(shí),卻可以順利地和Server組件進(jìn)行進(jìn)程間通信,這就是因?yàn)锳ndroid應(yīng)用程序進(jìn)程在創(chuàng)建的時(shí)候就已經(jīng)啟動(dòng)了一個(gè)線程池來(lái)支持Server組件和Binder驅(qū)動(dòng)程序之間的交互了,這樣,極大地方便了在Android應(yīng)用程序中創(chuàng)建Server組件。

            在Android應(yīng)用程序框架層中,是由ActivityManagerService組件負(fù)責(zé)為Android應(yīng)用程序創(chuàng)建新的進(jìn)程的,它本來(lái)也是運(yùn)行在一個(gè)獨(dú)立的進(jìn)程之中,不過(guò)這個(gè)進(jìn)程是在系統(tǒng)啟動(dòng)的過(guò)程中創(chuàng)建的。ActivityManagerService組件一般會(huì)在什么情況下會(huì)為應(yīng)用程序創(chuàng)建一個(gè)新的進(jìn)程呢?當(dāng)系統(tǒng)決定要在一個(gè)新的進(jìn)程中啟動(dòng)一個(gè)Activity或者Service時(shí),它就會(huì)創(chuàng)建一個(gè)新的進(jìn)程了,然后在這個(gè)新的進(jìn)程中啟動(dòng)這個(gè)Activity或者Service,具體可以參考Android系統(tǒng)在新進(jìn)程中啟動(dòng)自定義服務(wù)過(guò)程(startService)的原理分析Android應(yīng)用程序啟動(dòng)過(guò)程源代碼分析Android應(yīng)用程序在新的進(jìn)程中啟動(dòng)新的Activity的方法和過(guò)程分析這三篇文章。

            ActivityManagerService啟動(dòng)新的進(jìn)程是從其成員函數(shù)startProcessLocked開(kāi)始的,在深入分析這個(gè)過(guò)程之前,我們先來(lái)看一下進(jìn)程創(chuàng)建過(guò)程的序列圖,然后再詳細(xì)分析每一個(gè)步驟。


           點(diǎn)擊查看大圖

            Step 1. ActivityManagerService.startProcessLocked

            這個(gè)函數(shù)定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

    public final class ActivityManagerService extends ActivityManagerNative  
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
      
        ......  
      
        private final void startProcessLocked(ProcessRecord app,  
                    String hostingType, String hostingNameStr) {  
      
            ......  
      
            try {  
                int uid = app.info.uid;  
                int[] gids = null;  
                try {  
                    gids = mContext.getPackageManager().getPackageGids(  
                        app.info.packageName);  
                } catch (PackageManager.NameNotFoundException e) {  
                    ......  
                }  
                  
                ......  
      
                int debugFlags = 0;  
                  
                ......  
                  
                int pid = Process.start("android.app.ActivityThread",  
                    mSimpleProcessManagement ? app.processName : null, uid, uid,  
                    gids, debugFlags, null);  
                  
                ......  
      
            } catch (RuntimeException e) {  
                  
                ......  
      
            }  
        }  
      
        ......  
      
    }  
            它調(diào)用了Process.start函數(shù)開(kāi)始為應(yīng)用程序創(chuàng)建新的進(jìn)程,注意,它傳入一個(gè)第一個(gè)參數(shù)為"android.app.ActivityThread",這就是進(jìn)程初始化時(shí)要加載的Java類了,把這個(gè)類加載到進(jìn)程之后,就會(huì)把它里面的靜態(tài)成員函數(shù)main作為進(jìn)程的入口點(diǎn),后面我們會(huì)看到。

     

            Step 2. Process.start 

            這個(gè)函數(shù)定義在frameworks/base/core/java/android/os/Process.java文件中:

    public class Process {
    	......
    
    	public static final int start(final String processClass,
    		final String niceName,
    		int uid, int gid, int[] gids,
    		int debugFlags,
    		String[] zygoteArgs)
    	{
    		if (supportsProcesses()) {
    			try {
    				return startViaZygote(processClass, niceName, uid, gid, gids,
    					debugFlags, zygoteArgs);
    			} catch (ZygoteStartFailedEx ex) {
    				......
    			}
    		} else {
    			......
    
    			return 0;
    		}
    	}
    
    	......
    }
           這里的supportsProcesses函數(shù)返回值為true,它是一個(gè)Native函數(shù),實(shí)現(xiàn)在frameworks/base/core/jni/android_util_Process.cpp文件中:

     

    jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)
    {
        return ProcessState::self()->supportsProcesses();
    }

     

           ProcessState::supportsProcesses函數(shù)定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

    bool ProcessState::supportsProcesses() const
    {
        return mDriverFD >= 0;
    }
    
           這里的mDriverFD是設(shè)備文件/dev/binder的打開(kāi)描述符,如果成功打開(kāi)了這個(gè)設(shè)備文件,那么它的值就會(huì)大于等于0,因此,它的返回值為true。

     

           回到Process.start函數(shù)中,它調(diào)用startViaZygote函數(shù)進(jìn)一步操作。

           Step 3. Process.startViaZygote

           這個(gè)函數(shù)定義在frameworks/base/core/java/android/os/Process.java文件中:

    public class Process {
    	......
    
    	private static int startViaZygote(final String processClass,
    			final String niceName,
    			final int uid, final int gid,
    			final int[] gids,
    			int debugFlags,
    			String[] extraArgs)
    			throws ZygoteStartFailedEx {
    		int pid;
    
    		synchronized(Process.class) {
    			ArrayList<String> argsForZygote = new ArrayList<String>();
    
    			// --runtime-init, --setuid=, --setgid=,
    			// and --setgroups= must go first
    			argsForZygote.add("--runtime-init");
    			argsForZygote.add("--setuid=" + uid);
    			argsForZygote.add("--setgid=" + gid);
    			if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
    				argsForZygote.add("--enable-safemode");
    			}
    			if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
    				argsForZygote.add("--enable-debugger");
    			}
    			if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
    				argsForZygote.add("--enable-checkjni");
    			}
    			if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
    				argsForZygote.add("--enable-assert");
    			}
    
    			//TODO optionally enable debuger
    			//argsForZygote.add("--enable-debugger");
    
    			// --setgroups is a comma-separated list
    			if (gids != null && gids.length > 0) {
    				StringBuilder sb = new StringBuilder();
    				sb.append("--setgroups=");
    
    				int sz = gids.length;
    				for (int i = 0; i < sz; i++) {
    					if (i != 0) {
    						sb.append(',');
    					}
    					sb.append(gids[i]);
    				}
    
    				argsForZygote.add(sb.toString());
    			}
    
    			if (niceName != null) {
    				argsForZygote.add("--nice-name=" + niceName);
    			}
    
    			argsForZygote.add(processClass);
    
    			if (extraArgs != null) {
    				for (String arg : extraArgs) {
    					argsForZygote.add(arg);
    				}
    			}
    
    			pid = zygoteSendArgsAndGetPid(argsForZygote);
    		}
    	}
    
    	......
    }
            這個(gè)函數(shù)將創(chuàng)建進(jìn)程的參數(shù)放到argsForZygote列表中去,如參數(shù)"--runtime-init"表示要為新創(chuàng)建的進(jìn)程初始化運(yùn)行時(shí)庫(kù),然后調(diào)用zygoteSendAndGetPid函數(shù)進(jìn)一步操作。

     

            Step 4. Process.zygoteSendAndGetPid

            這個(gè)函數(shù)定義在frameworks/base/core/java/android/os/Process.java文件中:

    public class Process {
    	......
    
    	private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
    			throws ZygoteStartFailedEx {
    		int pid;
    
    		openZygoteSocketIfNeeded();
    
    		try {
    			/**
    			* See com.android.internal.os.ZygoteInit.readArgumentList()
    			* Presently the wire format to the zygote process is:
    			* a) a count of arguments (argc, in essence)
    			* b) a number of newline-separated argument strings equal to count
    			*
    			* After the zygote process reads these it will write the pid of
    			* the child or -1 on failure.
    			*/
    
    			sZygoteWriter.write(Integer.toString(args.size()));
    			sZygoteWriter.newLine();
    
    			int sz = args.size();
    			for (int i = 0; i < sz; i++) {
    				String arg = args.get(i);
    				if (arg.indexOf('\n') >= 0) {
    					throw new ZygoteStartFailedEx(
    						"embedded newlines not allowed");
    				}
    				sZygoteWriter.write(arg);
    				sZygoteWriter.newLine();
    			}
    
    			sZygoteWriter.flush();
    
    			// Should there be a timeout on this?
    			pid = sZygoteInputStream.readInt();
    
    			if (pid < 0) {
    				throw new ZygoteStartFailedEx("fork() failed");
    			}
    		} catch (IOException ex) {
    			......
    		}
    
    		return pid;
    	}
    
    	......
    }
             這里的sZygoteWriter是一個(gè)Socket寫(xiě)入流,是由openZygoteSocketIfNeeded函數(shù)打開(kāi)的:

     

    public class Process {
    	......
    
    	/**
    	* Tries to open socket to Zygote process if not already open. If
    	* already open, does nothing.  May block and retry.
    	*/
    	private static void openZygoteSocketIfNeeded()
    			throws ZygoteStartFailedEx {
    
    		int retryCount;
    
    		if (sPreviousZygoteOpenFailed) {
    			/*
    			* If we've failed before, expect that we'll fail again and
    			* don't pause for retries.
    			*/
    			retryCount = 0;
    		} else {
    			retryCount = 10;
    		}
    	
    		/*
    		* See bug #811181: Sometimes runtime can make it up before zygote.
    		* Really, we'd like to do something better to avoid this condition,
    		* but for now just wait a bit...
    		*/
    		for (int retry = 0
    			; (sZygoteSocket == null) && (retry < (retryCount + 1))
    			; retry++ ) {
    
    				if (retry > 0) {
    					try {
    						Log.i("Zygote", "Zygote not up yet, sleeping...");
    						Thread.sleep(ZYGOTE_RETRY_MILLIS);
    					} catch (InterruptedException ex) {
    						// should never happen
    					}
    				}
    
    				try {
    					sZygoteSocket = new LocalSocket();
    					sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
    						LocalSocketAddress.Namespace.RESERVED));
    
    					sZygoteInputStream
    						= new DataInputStream(sZygoteSocket.getInputStream());
    
    					sZygoteWriter =
    						new BufferedWriter(
    						new OutputStreamWriter(
    						sZygoteSocket.getOutputStream()),
    						256);
    
    					Log.i("Zygote", "Process: zygote socket opened");
    
    					sPreviousZygoteOpenFailed = false;
    					break;
    				} catch (IOException ex) {
    					......
    				}
    		}
    
    		......
    	}
    
    	......
    }
            這個(gè)Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit類在runSelectLoopMode函數(shù)偵聽(tīng)的。
            Step 5. ZygoteInit.runSelectLoopMode
            這個(gè)函數(shù)定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

     

    public class ZygoteInit {
    	......
    
    	/**
    	* Runs the zygote process's select loop. Accepts new connections as
    	* they happen, and reads commands from connections one spawn-request's
    	* worth at a time.
    	*
    	* @throws MethodAndArgsCaller in a child process when a main() should
    	* be executed.
    	*/
    	private static void runSelectLoopMode() throws MethodAndArgsCaller {
    		ArrayList<FileDescriptor> fds = new ArrayList();
    		ArrayList<ZygoteConnection> peers = new ArrayList();
    		FileDescriptor[] fdArray = new FileDescriptor[4];
    
    		fds.add(sServerSocket.getFileDescriptor());
    		peers.add(null);
    
    		int loopCount = GC_LOOP_COUNT;
    		while (true) {
    			int index;
    			/*
    			* Call gc() before we block in select().
    			* It's work that has to be done anyway, and it's better
    			* to avoid making every child do it.  It will also
    			* madvise() any free memory as a side-effect.
    			*
    			* Don't call it every time, because walking the entire
    			* heap is a lot of overhead to free a few hundred bytes.
    			*/
    			if (loopCount <= 0) {
    				gc();
    				loopCount = GC_LOOP_COUNT;
    			} else {
    				loopCount--;
    			}
    
    
    			try {
    				fdArray = fds.toArray(fdArray);
    				index = selectReadable(fdArray);
    			} catch (IOException ex) {
    				throw new RuntimeException("Error in select()", ex);
    			}
    
    			if (index < 0) {
    				throw new RuntimeException("Error in select()");
    			} else if (index == 0) {
    				ZygoteConnection newPeer = acceptCommandPeer();
    				peers.add(newPeer);
    				fds.add(newPeer.getFileDesciptor());
    			} else {
    				boolean done;
    				done = peers.get(index).runOnce();
    
    				if (done) {
    					peers.remove(index);
    					fds.remove(index);
    				}
    			}
    		}
    	}
    
    	......
    }
            當(dāng)Step 4將數(shù)據(jù)通過(guò)Socket接口發(fā)送出去后,就會(huì)下面這個(gè)語(yǔ)句:

     

    done = peers.get(index).runOnce();
            這里從peers.get(index)得到的是一個(gè)ZygoteConnection對(duì)象,表示一個(gè)Socket連接,因此,接下來(lái)就是調(diào)用ZygoteConnection.runOnce函數(shù)進(jìn)一步處理了。

     

            Step 6. ZygoteConnection.runOnce

            這個(gè)函數(shù)定義在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:

    class ZygoteConnection {
    	......
    
    	boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    		String args[];
    		Arguments parsedArgs = null;
    		FileDescriptor[] descriptors;
    
    		try {
    			args = readArgumentList();
    			descriptors = mSocket.getAncillaryFileDescriptors();
    		} catch (IOException ex) {
    			......
    			return true;
    		}
    
    		......
    
    		/** the stderr of the most recent request, if avail */
    		PrintStream newStderr = null;
    
    		if (descriptors != null && descriptors.length >= 3) {
    			newStderr = new PrintStream(
    				new FileOutputStream(descriptors[2]));
    		}
    
    		int pid;
    		
    		try {
    			parsedArgs = new Arguments(args);
    
    			applyUidSecurityPolicy(parsedArgs, peer);
    			applyDebuggerSecurityPolicy(parsedArgs);
    			applyRlimitSecurityPolicy(parsedArgs, peer);
    			applyCapabilitiesSecurityPolicy(parsedArgs, peer);
    
    			int[][] rlimits = null;
    
    			if (parsedArgs.rlimits != null) {
    				rlimits = parsedArgs.rlimits.toArray(intArray2d);
    			}
    
    			pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
    				parsedArgs.gids, parsedArgs.debugFlags, rlimits);
    		} catch (IllegalArgumentException ex) {
    			......
    		} catch (ZygoteSecurityException ex) {
    			......
    		}
    
    		if (pid == 0) {
    			// in child
    			handleChildProc(parsedArgs, descriptors, newStderr);
    			// should never happen
    			return true;
    		} else { /* pid != 0 */
    			// in parent...pid of < 0 means failure
    			return handleParentProc(pid, descriptors, parsedArgs);
    		}
    	}
    
    	......
    }
             真正創(chuàng)建進(jìn)程的地方就是在這里了:

     

    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
    	parsedArgs.gids, parsedArgs.debugFlags, rlimits);
            有Linux開(kāi)發(fā)經(jīng)驗(yàn)的讀者很容易看懂這個(gè)函數(shù)調(diào)用,這個(gè)函數(shù)會(huì)創(chuàng)建一個(gè)進(jìn)程,而且有兩個(gè)返回值,一個(gè)是在當(dāng)前進(jìn)程中返回的,一個(gè)是在新創(chuàng)建的進(jìn)程中返回,即在當(dāng)前進(jìn)程的子進(jìn)程中返回,在當(dāng)前進(jìn)程中的返回值就是新創(chuàng)建的子進(jìn)程的pid值,而在子進(jìn)程中的返回值是0。因?yàn)槲覀冎魂P(guān)心創(chuàng)建的新進(jìn)程的情況,因此,我們沿著子進(jìn)程的執(zhí)行路徑繼續(xù)看下去:

     

        if (pid == 0) {
    	// in child
    	handleChildProc(parsedArgs, descriptors, newStderr);
    	// should never happen
    	return true;
        } else { /* pid != 0 */
    	......
        }
            這里就是調(diào)用handleChildProc函數(shù)了。

     

            Step 7. ZygoteConnection.handleChildProc
            這個(gè)函數(shù)定義在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:

    class ZygoteConnection {
    	......
    
    	private void handleChildProc(Arguments parsedArgs,
    			FileDescriptor[] descriptors, PrintStream newStderr)
    			throws ZygoteInit.MethodAndArgsCaller {
    		......
    
    		if (parsedArgs.runtimeInit) {
    			RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
    		} else {
    			......
    		}
    	}
    
    	......
    }
            由于在前面的Step 3中,指定了"--runtime-init"參數(shù),表示要為新創(chuàng)建的進(jìn)程初始化運(yùn)行時(shí)庫(kù),因此,這里的parseArgs.runtimeInit值為true,于是就繼續(xù)執(zhí)行RuntimeInit.zygoteInit進(jìn)一步處理了。

     

            Step 8. RuntimeInit.zygoteInit

            這個(gè)函數(shù)定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

    public class RuntimeInit {
    	......
    
    	public static final void zygoteInit(String[] argv)
    			throws ZygoteInit.MethodAndArgsCaller {
    		// TODO: Doing this here works, but it seems kind of arbitrary. Find
    		// a better place. The goal is to set it up for applications, but not
    		// tools like am.
    		System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
    		System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
    
    		commonInit();
    		zygoteInitNative();
    
    		int curArg = 0;
    		for ( /* curArg */ ; curArg < argv.length; curArg++) {
    			String arg = argv[curArg];
    
    			if (arg.equals("--")) {
    				curArg++;
    				break;
    			} else if (!arg.startsWith("--")) {
    				break;
    			} else if (arg.startsWith("--nice-name=")) {
    				String niceName = arg.substring(arg.indexOf('=') + 1);
    				Process.setArgV0(niceName);
    			}
    		}
    
    		if (curArg == argv.length) {
    			Slog.e(TAG, "Missing classname argument to RuntimeInit!");
    			// let the process exit
    			return;
    		}
    
    		// Remaining arguments are passed to the start class's static main
    
    		String startClass = argv[curArg++];
    		String[] startArgs = new String[argv.length - curArg];
    
    		System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
    		invokeStaticMain(startClass, startArgs);
    	}
    
    	......
    }
            這里有兩個(gè)關(guān)鍵的函數(shù)調(diào)用,一個(gè)是zygoteInitNative函數(shù)調(diào)用,一個(gè)是invokeStaticMain函數(shù)調(diào)用,前者就是執(zhí)行Binder驅(qū)動(dòng)程序初始化的相關(guān)工作了,正是由于執(zhí)行了這個(gè)工作,才使得進(jìn)程中的Binder對(duì)象能夠順利地進(jìn)行Binder進(jìn)程間通信,而后一個(gè)函數(shù)調(diào)用,就是執(zhí)行進(jìn)程的入口函數(shù),這里就是執(zhí)行startClass類的main函數(shù)了,而這個(gè)startClass即是我們?cè)赟tep 1中傳進(jìn)來(lái)的"android.app.ActivityThread"值,表示要執(zhí)行android.app.ActivityThread類的main函數(shù)。

     

            我們先來(lái)看一下zygoteInitNative函數(shù)的調(diào)用過(guò)程,然后再回到RuntimeInit.zygoteInit函數(shù)中來(lái),看看它是如何調(diào)用android.app.ActivityThread類的main函數(shù)的。

            step 9. RuntimeInit.zygoteInitNative

            這個(gè)函數(shù)定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

    public class RuntimeInit {
    	......
    
    	public static final native void zygoteInitNative();
    
    	......
    }
            這里可以看出,函數(shù)zygoteInitNative是一個(gè)Native函數(shù),實(shí)現(xiàn)在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

     

    static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
    {
        gCurRuntime->onZygoteInit();
    }

     

            這里它調(diào)用了全局變量gCurRuntime的onZygoteInit函數(shù),這個(gè)全局變量的定義在frameworks/base/core/jni/AndroidRuntime.cpp文件開(kāi)頭的地方:

    static AndroidRuntime* gCurRuntime = NULL;
    
            這里可以看出,它的類型為AndroidRuntime,它是在AndroidRuntime類的構(gòu)造函數(shù)中初始化的,AndroidRuntime類的構(gòu)造函數(shù)也是定義在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

     

    AndroidRuntime::AndroidRuntime()
    {
        ......
    
        assert(gCurRuntime == NULL);        // one per process
        gCurRuntime = this;
    }
    
            那么這個(gè)AndroidRuntime類的構(gòu)造函數(shù)又是什么時(shí)候被調(diào)用的呢?AndroidRuntime類的聲明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中,如果我們打開(kāi)這個(gè)文件會(huì)看到,它是一個(gè)虛擬類,也就是我們不能直接創(chuàng)建一個(gè)AndroidRuntime對(duì)象,只能用一個(gè)AndroidRuntime類的指針來(lái)指向它的某一個(gè)子類,這個(gè)子類就是AppRuntime了,它定義在frameworks/base/cmds/app_process/app_main.cpp文件中:

     

    int main(int argc, const char* const argv[])
    {
    	......
    
    	AppRuntime runtime;
    	
    	......
    }
            而AppRuntime類繼續(xù)了AndroidRuntime類,它也是定義在frameworks/base/cmds/app_process/app_main.cpp文件中:
    class AppRuntime : public AndroidRuntime
    {
    	......
    
    };
    
            因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函數(shù),實(shí)際是執(zhí)行了AppRuntime類的onZygoteInit函數(shù)。

     

            Step 10. AppRuntime.onZygoteInit
            這個(gè)函數(shù)定義在frameworks/base/cmds/app_process/app_main.cpp文件中:

    class AppRuntime : public AndroidRuntime
    {
    	......
    
    	virtual void onZygoteInit()
    	{
    		sp<ProcessState> proc = ProcessState::self();
    		if (proc->supportsProcesses()) {
    			LOGV("App process: starting thread pool.\n");
    			proc->startThreadPool();
    		}
    	}
    
    	......
    };
            這里它就是調(diào)用ProcessState::startThreadPool啟動(dòng)線程池了,這個(gè)線程池中的線程就是用來(lái)和Binder驅(qū)動(dòng)程序進(jìn)行交互的了。
            Step 11. ProcessState.startThreadPool
            這個(gè)函數(shù)定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

     

    void ProcessState::startThreadPool()
    {
    	AutoMutex _l(mLock);
    	if (!mThreadPoolStarted) {
    		mThreadPoolStarted = true;
    		spawnPooledThread(true);
    	}
    }
            ProcessState類是Binder進(jìn)程間通信機(jī)制的一個(gè)基礎(chǔ)組件,它的作用可以參考淺談Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server和Client獲得Service Manager接口之路Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server啟動(dòng)過(guò)程源代碼分析Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Client獲得Server遠(yuǎn)程接口過(guò)程源代碼分析這三篇文章。這里它調(diào)用spawnPooledThread函數(shù)進(jìn)一步處理。

     

            Step 12. ProcessState.spawnPooledThread

            這個(gè)函數(shù)定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

    void ProcessState::spawnPooledThread(bool isMain)
    {
        if (mThreadPoolStarted) {
            int32_t s = android_atomic_add(1, &mThreadPoolSeq);
            char buf[32];
            sprintf(buf, "Binder Thread #%d", s);
            LOGV("Spawning new pooled thread, name=%s\n", buf);
            sp<Thread> t = new PoolThread(isMain);
            t->run(buf);
        }
    }
    
            這里它會(huì)創(chuàng)建一個(gè)PoolThread線程類,然后執(zhí)行它的run函數(shù),最終就會(huì)執(zhí)行PoolThread類的threadLoop函數(shù)了。

     

            Step 13. PoolThread.threadLoop

            這個(gè)函數(shù)定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

    class PoolThread : public Thread
    {
    public:
        PoolThread(bool isMain)
            : mIsMain(isMain)
        {
        }
    
    protected:
        virtual bool threadLoop()
        {
            IPCThreadState::self()->joinThreadPool(mIsMain);
            return false;
        }
    
        const bool mIsMain;
    };
    
            這里它執(zhí)行了IPCThreadState::joinThreadPool函數(shù)進(jìn)一步處理。IPCThreadState也是Binder進(jìn)程間通信機(jī)制的一個(gè)基礎(chǔ)組件,它的作用可以參考淺談Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server和Client獲得Service Manager接口之路Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server啟動(dòng)過(guò)程源代碼分析Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Client獲得Server遠(yuǎn)程接口過(guò)程源代碼分析這三篇文章。

     

            Step 14. IPCThreadState.joinThreadPool

            這個(gè)函數(shù)定義在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

    void IPCThreadState::joinThreadPool(bool isMain)
    {
    	......
    
    	mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
    
    	......
    
    	status_t result;
    	do {
    		int32_t cmd;
    
    		......
    
    		// now get the next command to be processed, waiting if necessary
    		result = talkWithDriver();
    		if (result >= NO_ERROR) {
    			size_t IN = mIn.dataAvail();
    			if (IN < sizeof(int32_t)) continue;
    			cmd = mIn.readInt32();
    			......
    
    			result = executeCommand(cmd);
    		}
    
    		......
    	} while (result != -ECONNREFUSED && result != -EBADF);
    
    	......
    	
    	mOut.writeInt32(BC_EXIT_LOOPER);
    	talkWithDriver(false);
    }
            這個(gè)函數(shù)首先告訴Binder驅(qū)動(dòng)程序,這條線程要進(jìn)入循環(huán)了:

     

    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
            然后在中間的while循環(huán)中通過(guò)talkWithDriver不斷與Binder驅(qū)動(dòng)程序進(jìn)行交互,以便獲得Client端的進(jìn)程間調(diào)用:

     

    result = talkWithDriver();
            獲得了Client端的進(jìn)程間調(diào)用后,就調(diào)用excuteCommand函數(shù)來(lái)處理這個(gè)請(qǐng)求:

     

    result = executeCommand(cmd);
            最后,線程退出時(shí),也會(huì)告訴Binder驅(qū)動(dòng)程序,它退出了,這樣Binder驅(qū)動(dòng)程序就不會(huì)再在Client端的進(jìn)程間調(diào)用分發(fā)給它了:

     

    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
            我們?cè)賮?lái)看看talkWithDriver函數(shù)的實(shí)現(xiàn)。

     

            Step 15. talkWithDriver

            這個(gè)函數(shù)定義在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

    status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
    	......
    
    	binder_write_read bwr;
    
    	// Is the read buffer empty?
    	const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    
    	// We don't want to write anything if we are still reading
    	// from data left in the input buffer and the caller
    	// has requested to read the next data.
    	const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
    
    	bwr.write_size = outAvail;
    	bwr.write_buffer = (long unsigned int)mOut.data();
    
    	// This is what we'll read.
    	if (doReceive && needRead) {
    		bwr.read_size = mIn.dataCapacity();
    		bwr.read_buffer = (long unsigned int)mIn.data();
    	} else {
    		bwr.read_size = 0;
    	}
    
    	......
    
    	// Return immediately if there is nothing to do.
    	if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
    
    	bwr.write_consumed = 0;
    	bwr.read_consumed = 0;
    	status_t err;
    	do {
    		......
    #if defined(HAVE_ANDROID_OS)
    		if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
    			err = NO_ERROR;
    		else
    			err = -errno;
    #else
    		err = INVALID_OPERATION;
    #endif
    		......
    		}
    	} while (err == -EINTR);
    
    	....
    
    	if (err >= NO_ERROR) {
    		if (bwr..write_consumed > 0) {
    			if (bwr.write_consumed < (ssize_t)mOut.dataSize())
    				mOut.remove(0, bwr.write_consumed);
    			else
    				mOut.setDataSize(0);
    		}
    		if (bwr.read_consumed > 0) {
    			mIn.setDataSize(bwr.read_consumed);
    			mIn.setDataPosition(0);
    		}
    		......
    		return NO_ERROR;
    	}
    
    	return err;
    }
            這個(gè)函數(shù)的具體作用可以參考Android系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder中的Server啟動(dòng)過(guò)程源代碼分析一文,它只要就是通過(guò)ioctl文件操作函數(shù)來(lái)和Binder驅(qū)動(dòng)程序交互的了:

     

    ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
            有了這個(gè)線程池之后,我們?cè)陂_(kāi)發(fā)Android應(yīng)用程序的時(shí)候,當(dāng)我們要和其它進(jìn)程中進(jìn)行通信時(shí),只要定義自己的Binder對(duì)象,然后把這個(gè)Binder對(duì)象的遠(yuǎn)程接口通過(guò)其它途徑傳給其它進(jìn)程后,其它進(jìn)程就可以通過(guò)這個(gè)Binder對(duì)象的遠(yuǎn)程接口來(lái)調(diào)用我們的應(yīng)用程序進(jìn)程的函數(shù)了,它不像我們?cè)贑++層實(shí)現(xiàn)Binder進(jìn)程間通信機(jī)制的Server時(shí),必須要手動(dòng)調(diào)用IPCThreadState.joinThreadPool函數(shù)來(lái)進(jìn)入一個(gè)無(wú)限循環(huán)中與Binder驅(qū)動(dòng)程序交互以便獲得Client端的請(qǐng)求,這樣就實(shí)現(xiàn)了我們?cè)谖恼麻_(kāi)頭處說(shuō)的Android應(yīng)用程序進(jìn)程天然地支持Binder進(jìn)程間通信機(jī)制。

     

            細(xì)心的讀者可能會(huì)發(fā)現(xiàn),從Step 1到Step 9,都是在Android應(yīng)用程序框架層運(yùn)行的,而從Step 10到Step 15,都是在Android系統(tǒng)運(yùn)行時(shí)庫(kù)層運(yùn)行的,這兩個(gè)層次中的Binder進(jìn)程間通信機(jī)制的接口一個(gè)是用Java來(lái)實(shí)現(xiàn)的,而別一個(gè)是用C++來(lái)實(shí)現(xiàn)的,這兩者是如何協(xié)作的呢?這就是通過(guò)JNI層來(lái)實(shí)現(xiàn)的了,具體可以參考Android系統(tǒng)進(jìn)程間通信Binder機(jī)制在應(yīng)用程序框架層的Java接口源代碼分析一文。

            回到Step 8中的RuntimeInit.zygoteInit函數(shù)中,在初始化完成Binder進(jìn)程間通信機(jī)制的基礎(chǔ)設(shè)施后,它接著就要進(jìn)入進(jìn)程的入口函數(shù)了。

            Step 16. RuntimeInit.invokeStaticMain

            這個(gè)函數(shù)定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

    public class ZygoteInit {
    	......
    
    	static void invokeStaticMain(ClassLoader loader,
    			String className, String[] argv)
    			throws ZygoteInit.MethodAndArgsCaller {
    		Class<?> cl;
    
    		try {
    			cl = loader.loadClass(className);
    		} catch (ClassNotFoundException ex) {
    			......
    		}
    
    		Method m;
    		try {
    			m = cl.getMethod("main", new Class[] { String[].class });
    		} catch (NoSuchMethodException ex) {
    			......
    		} catch (SecurityException ex) {
    			......
    		}
    
    		int modifiers = m.getModifiers();
    		......
    
    		/*
    		* This throw gets caught in ZygoteInit.main(), which responds
    		* by invoking the exception's run() method. This arrangement
    		* clears up all the stack frames that were required in setting
    		* up the process.
    		*/
    		throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    	}
    
    	......
    }
            前面我們說(shuō)過(guò),這里傳進(jìn)來(lái)的參數(shù)className字符串值為"android.app.ActivityThread",這里就通ClassLoader.loadClass函數(shù)將它加載到進(jìn)程中:

     

    cl = loader.loadClass(className);
            然后獲得它的靜態(tài)成員函數(shù)main:

     

    m = cl.getMethod("main", new Class[] { String[].class });
            函數(shù)最后并沒(méi)有直接調(diào)用這個(gè)靜態(tài)成員函數(shù)main,而是通過(guò)拋出一個(gè)異常ZygoteInit.MethodAndArgsCaller,然后讓ZygoteInit.main函數(shù)在捕獲這個(gè)異常的時(shí)候再調(diào)用android.app.ActivityThread類的main函數(shù)。為什么要這樣做呢?注釋里面已經(jīng)講得很清楚了,它是為了清理堆棧的,這樣就會(huì)讓android.app.ActivityThread類的main函數(shù)覺(jué)得自己是進(jìn)程的入口函數(shù),而事實(shí)上,在執(zhí)行android.app.ActivityThread類的main函數(shù)之前,已經(jīng)做了大量的工作了。

     

            我們看看ZygoteInit.main函數(shù)在捕獲到這個(gè)異常的時(shí)候做了什么事:

    public class ZygoteInit {
    	......
    
    	public static void main(String argv[]) {
    		try {
    			......
    		} catch (MethodAndArgsCaller caller) {
    			caller.run();
    		} catch (RuntimeException ex) {
    			......
    		}
    	}
    
    	......
    }
            它執(zhí)行MethodAndArgsCaller的run函數(shù):

     

    public class ZygoteInit {
    	......
    
    	public static class MethodAndArgsCaller extends Exception
    			implements Runnable {
    		/** method to call */
    		private final Method mMethod;
    
    		/** argument array */
    		private final String[] mArgs;
    
    		public MethodAndArgsCaller(Method method, String[] args) {
    			mMethod = method;
    			mArgs = args;
    		}
    
    		public void run() {
    			try {
    				mMethod.invoke(null, new Object[] { mArgs });
    			} catch (IllegalAccessException ex) {
    				......
    			} catch (InvocationTargetException ex) {
    				......
    			}
    		}
    	}
    
    	......
    }
            這里的成員變量mMethod和mArgs都是在前面構(gòu)造異常對(duì)象時(shí)傳進(jìn)來(lái)的,這里的mMethod就對(duì)應(yīng)android.app.ActivityThread類的main函數(shù)了,于是最后就通過(guò)下面語(yǔ)句執(zhí)行這個(gè)函數(shù):

     

    mMethod.invoke(null, new Object[] { mArgs });
            這樣,android.app.ActivityThread類的main函數(shù)就被執(zhí)行了。

     

            Step 17. ActivityThread.main

            這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:

    public final class ActivityThread {
    	......
    
    	public static final void main(String[] args) {
    		SamplingProfilerIntegration.start();
    
    		Process.setArgV0("<pre-initialized>");
    
    		Looper.prepareMainLooper();
    		if (sMainThreadHandler == null) {
    			sMainThreadHandler = new Handler();
    		}
    
    		ActivityThread thread = new ActivityThread();
    		thread.attach(false);
    
    		if (false) {
    			Looper.myLooper().setMessageLogging(new
    				LogPrinter(Log.DEBUG, "ActivityThread"));
    		}
    		Looper.loop();
    
    		if (Process.supportsProcesses()) {
    			throw new RuntimeException("Main thread loop unexpectedly exited");
    		}
    
    		thread.detach();
    		String name = (thread.mInitialApplication != null)
    			? thread.mInitialApplication.getPackageName()
    			: "<unknown>";
    		Slog.i(TAG, "Main thread of " + name + " is now exiting");
    	}
    
    	......
    }
            從這里我們可以看出,這個(gè)函數(shù)首先會(huì)在進(jìn)程中創(chuàng)建一個(gè)ActivityThread對(duì)象:

     

    ActivityThread thread = new ActivityThread();
            然后進(jìn)入消息循環(huán)中:

     

    Looper.loop();
            這樣,我們以后就可以在這個(gè)進(jìn)程中啟動(dòng)Activity或者Service了。

     

            至此,Android應(yīng)用程序進(jìn)程啟動(dòng)過(guò)程的源代碼就分析完成了,它除了指定新的進(jìn)程的入口函數(shù)是ActivityThread的main函數(shù)之外,還為進(jìn)程內(nèi)的Binder對(duì)象提供了Binder進(jìn)程間通信機(jī)制的基礎(chǔ)設(shè)施,由此可見(jiàn),Binder進(jìn)程間通信機(jī)制在Android系統(tǒng)中是何等的重要,而且是無(wú)處不在,想進(jìn)一步學(xué)習(xí)Android系統(tǒng)的Binder進(jìn)程間通信機(jī)制,請(qǐng)參考Android進(jìn)程間通信(IPC)機(jī)制Binder簡(jiǎn)要介紹和學(xué)習(xí)計(jì)劃一文。

    作者:Luoshengyang 發(fā)表于2011-9-9 1:01:32 原文鏈接
    閱讀:8086 評(píng)論:15 查看評(píng)論
    posted on 2012-04-17 21:32 mixer-a 閱讀(751) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 色屁屁在线观看视频免费| 毛片a级毛片免费观看免下载| 亚洲人成网站色在线观看| 亚洲综合另类小说色区| 国产高清不卡免费在线| 中文在线免费不卡视频| 国产亚洲精品仙踪林在线播放| 亚洲国产成人va在线观看网址| 国产av天堂亚洲国产av天堂 | 国产亚洲精品无码专区| 免费可以看黄的视频s色| 中文字幕久精品免费视频| 伊人久久国产免费观看视频| 亚洲国产成人综合精品| 亚洲人成网站看在线播放| 亚洲国语精品自产拍在线观看| 中文亚洲AV片在线观看不卡 | 亚洲欧美中文日韩视频| 亚洲成av人片不卡无码| 亚洲日本一区二区| 亚洲AV日韩AV高潮无码专区| 亚洲色精品vr一区二区三区| 国产精品亚洲mnbav网站| 一本久到久久亚洲综合| 亚洲av无码成人精品区| 免费人成年激情视频在线观看| 国产无遮挡色视频免费视频| 大陆一级毛片免费视频观看i| 最近免费中文字幕视频高清在线看| 91频在线观看免费大全| 无码区日韩特区永久免费系列 | 亚洲精品WWW久久久久久| 日批日出水久久亚洲精品tv| 免费一级毛片不卡在线播放| 国产精品麻豆免费版| 国产成人精品免费视频软件| 国产一级淫片a免费播放口之| 免费不卡中文字幕在线| 亚洲国产专区一区| 国产综合亚洲专区在线| 亚洲人成网77777亚洲色|