Android source code analysis-system_server Process Analysis

Source: Internet
Author: User

Android source code analysis-system_server Process Analysis

In the previous blog, we analyzed the Zygote process. We know that the Zygote process creates an important process-the system_server process and enters an infinite loop, later, an important task in the Android system was handed over to the system_server process. As the eldest son process of zygote, The system_server process is of extraordinary significance. Today we will analyze the system_server process.

Create a system_server Process

In the main method of ZygoteInit, The system_server process is enabled by calling the startSystemServer method. This method mainly prepares some parameters for the system_server Process and calls the local method forkSystemServer to create the system_server process. Let's take a look at the code of the startSystemServer method:

Private static boolean startSystemServer () throws MethodAndArgsCaller, RuntimeException {String args [] = {"-- setuid = 1000", "-- setgid = 1000", "-- setgroups = 1001,1002, 1003,1004, 3007, "-- capabilities = Hangzhou", "-- runtime-init", "-- nice-name = system_server ", "com. android. server. systemServer ",}; ZygoteConnection. arguments parsedArgs = null; int pid; try {parsedArgs = new ZygoteConnection. arguments (args); ZygoteConnection. applyDebuggerSystemProperty (parsedArgs); ZygoteConnection. applyInvokeWithSystemProperty (parsedArgs);/* Create a system_server process */pid = Zygote. forkSystemServer (parsedArgs. uid, parsedArgs. gid, parsedArgs. gids, parsedArgs. debugFlags, null, parsedArgs. permittedCapabilities, parsedArgs. effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException (ex);}/* execute */if (pid = 0) {handleSystemServerProcess (parsedArgs) in the child process );} return true ;}

The code here is not complex. We can see that he calls the forkSystemServer method to create a new process and then executes the handleSystemServerProcess method in the sub-process, namely, the system_server process. Next let's take a look at the forkSystemServer method. It is the source file of a native method in dalvik \ vm \ native \ dalvik_system_Zygote.cpp. The Code is as follows:

Static void Dalvik_dalvik_system_Zygote_forkSystemServer (const u4 * args, JValue * pResult) {pid_t pid; pid = forkAndSpecializeCommon (args, true ); /* zygote process check whether its child process is dead */if (pid> 0) {int status; ALOGI ("System server process % d has been created", pid); gDvm. systemServerPid = pid;/* if the system_server process exits, the zygote process will also be killed */if (waitpid (pid, & status, WNOHANG) = pid) {ALOGE ("System server process % d Has died. Restarting Zygote! ", Pid); kill (getpid (), SIGKILL) ;}} RETURN_INT (pid );}

From the code, we can see that in the forkAndSpecializeCommon method, we created a sub-process and returned the sub-process id. Next, I will check if the system_server process exits, if so, the zygote process will also be killed, which shows its importance. Next let's take a look at the forkAndSpecializeCommon code. The creation of this system_server process is truly a hundred revolutions...

Static pid_t forward (const u4 * args, bool isSystemServer) {pid_t pid; uid_t uid = (uid_t) args [0]; gid_t gid = (gid_t) args [1]; arrayObject * gids = (ArrayObject *) args [2]; u4 debugFlags = args [3]; ArrayObject * rlimits = (ArrayObject *) args [4]; u4 mountMode = MOUNT_EXTERNAL_NONE; int64_t permittedCapabilities, effectiveCapabilities; char * seInfo = NULL; char * niceName = NULL; // input parameter I SSystemServer is true if (isSystemServer) {permittedCapabilities = args [5] | (int64_t) args [6] <32; effectiveCapabilities = args [7] | (int64_t) args [8] <32;} else {......} if (! GDvm. zygote) {dvmThrowIllegalStateException ("VM instance not started with-Xzygote"); return-1 ;}// call if (! DvmGcPreZygoteFork () {ALOGE ("pre-fork heap failed"); dvmAbort ();} setSignalHandler (); // write some data to the log file dvmDumpLoaderStats ("zygote"); // The Subprocess is fork and the pid is fork (); if (pid = 0) {// process the child process according to the input parameters, for example, set the process name and various IDs ......} return pid ;}

At this point, the system_server process is finally created. We can see that the system_server process is also split and cloned through the Fork mechanism unique to the Linux system. Before fork, we still have an important method not to analyze-setSignalHandler method. This method is used to set signal processing. Let's take a look at it.

Static void setSignalHandler () {int err; struct sigaction sa; memset (& sa, 0, sizeof (sa); sa. sa_handler = sigchldHandler; err = sigaction (SIGCHLD, & sa, NULL); // sets the signal processing function. The signal is the signal of sub-process death if (err <0) {ALOGW ("Error setting SIGCHLD handler: % s", strerror (errno) ;}} static void sigchldHandler (int s) {pid_t pid; int status; while (pid = waitpid (-1, & status, WNOHANG)> 0) {/* print the death state of the process we are concerned about. */...... /** if the destroyed process is system_server and the zygote process is killed *, The system_server process and zygote process will be restarted by the init process */if (pid = gDvm. systemServerPid) {ALOG (LOG_INFO, ZYGOTE_LOG_TAG, "Exit zygote because system server (% d) has terminated", (int) pid); kill (getpid (), SIGKILL );}} if (pid <0) {ALOG (LOG_WARN, ZYGOTE_LOG_TAG, "Zygote SIGCHLD error in waitpid: % s", strerror (errno ));}}

Here we have seen that the system_server process has been checked for death in the forkSystemServer method. Why should we perform another check here? This is to prevent the system_server process from dying when the fork sub-process pid is not obtained.

Summary: the creation of the system_server process has gone through a long process: first, startSystemServer calls the native method forkSystemServer; then, the native method forkSystemServer calls the forkAndSpecializeCommon method; in the forkAndSpecializeCommon method, setSignalHandler was also called before fork to set signal processing items. In this way, our system_server process is finally created, and it also maintains a co-occurrence relationship with the zygote process.

Responsibilities of the system_server Process

In the startSystemServer method, we can see that after the process is created, the handleSystemServerProcess method will be executed in the sub-process, namely the system_server process. This is the responsibility of system_server. Let's take a look at it below:

Private static void handleSystemServerProcess (ZygoteConnection. arguments parsedArgs) throws ZygoteInit. methodAndArgsCaller {closeServerSocket (); // sets the permission. libcore. OS. umask (S_IRWXG | S_IRWXO );...... if (parsedArgs. invokeWith! = Null) {...} else {/* the remaining parameters are passed to SystemServer. */RuntimeInit.zygoteInit(parsedArgs.tar getSdkVersion, parsedArgs. remainingArgs );}}

The last system_server process comes to RuntimeInit. Its implementation is in frameworks \ base \ core \ java \ com \ android \ internal \ OS \ RuntimeInit. java.

Public static final void zygoteInit (int targetSdkVersion, String [] argv) throws ZygoteInit. methodAndArgsCaller {if (DEBUG) Slog. d (TAG, "RuntimeInit: Starting application from zygote"); // disable System. out and System. err, use Android log redirectLogStreams (); // do some common initialization commonInit (); // native layer initialization. After this method is called, system_server will establish a contact with the Binder communication system, in this way, you can use the Binder nativeZygoteInit (); applicationInit (targetSdkVersion, argv);} private static void applicationInit (int targetSdkVersion, String [] argv) throws ZygoteInit. methodAndArgsCaller {...... try {args = new Arguments (argv);} catch (IllegalArgumentException ex) {Slog. e (TAG, ex. getMessage (); // let the process exit return;} invokeStaticMain (args. startClass, args. startArgs );}

We can see that the invokeStaticMain method is called. The input parameter of this method is set in the startSystemServer method. The class name of the input parameter is "com. android. server. SystemServer"

Private static void invokeStaticMain (String className, String [] argv) throws ZygoteInit. MethodAndArgsCaller {Class
  Cl; try {cl = Class. forName (className);} catch (ClassNotFoundException ex) {throw new RuntimeException ("Missing class when invoking static main" + className, ex);} Method m; try {m = cl. getMethod ("main", new Class [] {String []. class});} catch (NoSuchMethodException ex) {throw new RuntimeException ("Missing static main on" + className, ex);} catch (SecurityException ex) {throw new Runti MeException ("Problem getting static main on" + className, ex);} int modifiers = m. getModifiers (); if (! (Modifier. isStatic (modifiers) & Modifier. isPublic (modifiers) {throw new RuntimeException ("Main method is not public and static on" + className);}/* throws exceptions in ZygoteInit. intercepted in main () */throw new ZygoteInit. methodAndArgsCaller (m, argv );}

Let's take a look at the intercepted statements:

Catch (MethodAndArgsCaller caller) {caller. run (); // call the caller run method}

Run method code:

public void run() {            try {                mMethod.invoke(null, new Object[] { mArgs });            } catch (IllegalAccessException ex) {                throw new RuntimeException(ex);            } catch (InvocationTargetException ex) {                Throwable cause = ex.getCause();                if (cause instanceof RuntimeException) {                    throw (RuntimeException) cause;                } else if (cause instanceof Error) {                    throw (Error) cause;                }                throw new RuntimeException(ex);            }        }

We can see that an exception is thrown at the end of the function, in ZygoteInit. main () is intercepted because the passed parameter class name is "com. android. server. systemServer ", so we call MethodAndArgsCaller. the run () method executes the static main method of the SystemServer class. (For more information about ZygoteInit, refer to the previous blog: Android source code analysis-Zygote Process Analysis)

Public static void main (String [] args) {...... // Mmmmmm... more memory! Dalvik. system. VMRuntime. getRuntime (). clearGrowthLimit (); // The system server is always running, so he needs to make full use of the memory VMRuntime. getRuntime (). setTargetHeapUtilization (0.8f); Environment. setUserRequired (true); System. loadLibrary ("android_servers"); Slog. I (TAG, "Entered the Android system server! "); // Native method, initialize some sensor services nativeInit (); // create a separate thread, start ServerThread thr = new ServerThread (); thr. initAndLoop ();}

Finally, system_server opened a new thread and executed its initAndLoop method, which is also defined in SystemServer. in java, this method has a lot of code. Its main task is to enable various services in the system, such as battery services and Bluetooth services. The logoff preparemainlogoff method is called to cycle the message and process the message.

Finally, let's summarize:

First, system_server executes the handleSystemServerProcess method to complete its mission, and then calls RuntimeInit. zygoteInit method. Here we have made some general initialization work that has been initialized on the native layer to establish a contact with the Binder. Then we call the invokeStaticMain method, use the thrown exception method to intercept and execute the main method of SystemServer in the main method of ZygoteInit. In the main method of SystemServer, I call the nativeInit method to initialize some sensor services, the separate thread is enabled to enable various services in the Android system, and The logoff preparemainlogoff method is called to loop messages, and then process messages.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.