当前位置: 首页 > news >正文

学年论文网站建设石家庄关键词优化软件

学年论文网站建设,石家庄关键词优化软件,建站工具原理,官方网站数据如何做脚注前言#xff1a;从开机的那一刻#xff0c;到开机完成后launcher将所有应用进行图标展示的这个过程#xff0c;大概会有哪一些操作#xff1f;执行了哪些代码#xff1f;作为Android开发工程师的我们#xff0c;有必要好好的梳理一遍。既然要梳理Android系统的启动流程从开机的那一刻到开机完成后launcher将所有应用进行图标展示的这个过程大概会有哪一些操作执行了哪些代码作为Android开发工程师的我们有必要好好的梳理一遍。 既然要梳理Android系统的启动流程那我们不可避免的需要阅读源码。这个过程的代码非常多我们只需要读一些关键的代码就可以大概的了解该流程。为了让读者更容易理解思路更加清晰可以先看下面的流程图 上图是打开电源后会开启的进程或者会执行的程序顺序之后分析的代码流程也是按照这个顺序来进行说明的。在后面的代码说明当中读者可以回过头来好好体会这个流程图。不同的Android版本的源码代码执行方法或者流程会略有不同这里的代码讲解是基于Android 8.0的。电源启动 当电源被按下之后固化在Rom的指定代码程序会被执行。该代码会将引导程序BootLoader加载到RAM中。BootLoader引导程序 BootLoader是一个引导程序该代码被加载到RAM 便开始执行它的主要作用是将系统拉起变并运行起来。Linux内核启动 Linux内核启动后会进行一些系统设置如缓存设置、计划列表、加载驱动等。在完成这些系统设置之后它会在系统文件中找到init.rc文件并且启动init进程。init进程 4.1 init进程的入口函数 init顾名思义就是初始化的意思init进程主要是做一些系统初始化的工作我们查看一下init进程的入口函数main。system/core/init/init.cppint main(int argc, char** argv) {if (!strcmp(basename(argv[0]), ueventd)) {return ueventd_main(argc, argv);}if (!strcmp(basename(argv[0]), watchdogd)) {return watchdogd_main(argc, argv);}if (REBOOT_BOOTLOADER_ON_PANIC) {install_reboot_signal_handlers();}add_environment(PATH, _PATH_DEFPATH);bool is_first_stage (getenv(INIT_SECOND_STAGE) nullptr);if (is_first_stage) {boot_clock::time_point start_time boot_clock::now();// Clear the umask.umask(0);// Get the basic filesystem setup we need put together in the initramdisk// on / and then well let the rc file figure out the rest.mount(tmpfs, /dev, tmpfs, MS_NOSUID, mode0755);mkdir(/dev/pts, 0755);mkdir(/dev/socket, 0755);mount(devpts, /dev/pts, devpts, 0, NULL);#define MAKE_STR(x) __STRING(x)mount(proc, /proc, proc, 0, hidepid2,gid MAKE_STR(AID_READPROC));// Dont expose the raw commandline to unprivileged processes.chmod(/proc/cmdline, 0440);gid_t groups[] { AID_READPROC };setgroups(arraysize(groups), groups);mount(sysfs, /sys, sysfs, 0, NULL);mount(selinuxfs, /sys/fs/selinux, selinuxfs, 0, NULL);mknod(/dev/kmsg, S_IFCHR | 0600, makedev(1, 11));mknod(/dev/random, S_IFCHR | 0666, makedev(1, 8));mknod(/dev/urandom, S_IFCHR | 0666, makedev(1, 9));......}......property_init(); //(1)......signal_handler_init(); //(2)......start_property_service(); //(3)set_usb_controller();......std::string bootscript GetProperty(ro.boot.init_rc, );if (bootscript.empty()) {parser.ParseConfig(/init.rc); //(4)parser.set_is_system_etc_init_loaded(parser.ParseConfig(/system/etc/init));parser.set_is_vendor_etc_init_loaded(parser.ParseConfig(/vendor/etc/init));parser.set_is_odm_etc_init_loaded(parser.ParseConfig(/odm/etc/init));} else {parser.ParseConfig(bootscript);parser.set_is_system_etc_init_loaded(true);parser.set_is_vendor_etc_init_loaded(true);parser.set_is_odm_etc_init_loaded(true);}......return 0; } init的main函数一开始创建和挂载了一些文件目录其中挂载了tmpfs、devpts、proc、sysfs、selinuxfs。 在注释1处调用了property_init函数对属性进行初始化然后在注释3处调用了start_property_service函数启动属性服务。在注释(2)处调用了signal_handler_init函数用于设置子进程信号处理函数它被定义在sysstem/core/init/signal_handler.cpp文件中该函数是用来处理暂停和终止的子进程的子进程在暂停或者结束的时候系统会发出SIGCHLD信号signal_handler_init函数是用来接收并且处理这种信号的。 例如在init进程中启动的某个子进程终止了系统即会发出进程终止的SIGCHLD信号signal_handler_init函数接收到了这个信号会调用signal_handler函数然后一层层的函数调用处理最终找到该子进程在这个处理中清除所有该子进程相关的信息。如果该子进程配置有onrestart选项的服务等将会被清理后重启。 注释4处调用了system/core/init/init_parser.cpp中的ParseConfig()方法解析了init.rc文件。4.2 init.rc配置文件 init.rc是一个重要的配置文件文件中使用了一种脚本语言这种脚本语言为Android初始化语言Android Init Language, 这种语言主要包含了五种类型语句。on init //(1)sysclktz 0# Mix device-specific information into the entropy poolcopy /proc/cmdline /dev/urandom //(2)copy /default.prop /dev/urandom# Backward compatibility.symlink /system/etc /etcsymlink /sys/kernel/debug /d# Link /vendor to /system/vendor for devices without a vendor partition.symlink /system/vendor /vendor# Mount cgroup mount point for cpu accountingmount cgroup none /acct cpuacctmkdir /acct/uid...... 例如以上截取的init.rc部分代码。on init 是Action 类型语句他的格式如下所示on trigger [ trigger]* //设置触发器command //触发动作之后要执行的命令command...... 根据格式如上面截取的代码注释1的on init 是触发器。而注释2处的“copy /proc/cmdline /dev/urandom”是command命令语句解释为复制/proc/cmdline 到/dev/urandom。 以上我们知道了init.rc文件中Android初始化语言中Action语句的格式和例子接下来为了了解在init中如何创建Zygote进程的我们来看看init.rc中的Service类型语句它的格式如下所示service name pathname [argument] * //service的名字执行程序的路径参数option //option是service的修饰词例如描述什么时候启动service,使用什么方式启动等option......在Android8.0中Zygote进程的启动脚本在init.zygoteXX.rc中定义在该目录文件夹下有init.zygote32.rc、init.zygote32_64.rc、init.zygote64.rc、init.zygote64_32.rc。init.zygote32_64.rc为既支持32位处理器又支持64位处理器但主要为32位处理器。其他三个文件也是类似原理区分。以下我们拿init.zygote64.rc为例讲解。service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server //1class main //2priority -20user rootgroup root readprocsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart audioserver //(3)onrestart restart cameraserver //4onrestart restart mediaonrestart restart netdonrestart restart wificondwritepid /dev/cpuset/foreground/tasks 以上是init.zygote64.rc里的内容根据上面提到的Service类型语句的根式注释1意思为通知init进程创建名为Zygote的进程这个进程执行程序的路径为/system/bin/app_process64,而后面的“-Xzygote /system/bin --zygote --start-system-server”均为传递的参数将传给app_process64。注释2是该服务的相关描述意思为classname为main。注释3、4的意思为当andioserver或者cameraserver等进程终止了就需要restart、既重启这些进程。其他的onrestart的相关描述语句也是如此。4.3 解析init.rc中的service语句 上面init.rc中我们提到的Action类型语句和Service类型语句这两种语句需要不同的类来进行解析。 回到4.1中的注释4”parser.ParseConfig(/init.rc);“调用了system/core/init/init_parser.cpp中的ParseConfig()函数在ParseConfig()函数中经过层层的调用最终会找到system/core/init/action.cpp中的ActionParser和system/core/init/service.cpp的ServiceParser分别解析Action类型语句和Service类型语句。 在这里主要是了解zygote的启动而zygote是通过前面提到的service类型语句启动的所以我们主要来看ServiceParser。 ServiceParser的实现代码在system/core/init/service.cpp中ServiceParser对Service类型语句的解析主要用到两个函数分别是ParseSection()和ParseLineSection()。bool ServiceParser::ParseSection(const std::vectorstd::string args,std::string* err) {if (args.size() 3) {*err services must have a name and a program;return false;}const std::string name args[1];if (!IsValidName(name)) {*err StringPrintf(invalid service name %s, name.c_str());return false;}std::vectorstd::string str_args(args.begin() 2, args.end());service_ std::make_uniqueService(name, str_args); //(1)return true; } bool ServiceParser::ParseLineSection(const std::vectorstd::string args,const std::string filename, int line,std::string* err) const {return service_ ? service_-ParseLine(args, err) : false; } 在注释1处会根据参数创造出一个Service对象。当解析完所有的数据之后会调用system/core/init/service.cpp中的EndSection()函数。void ServiceParser::EndSection() {if (service_) {ServiceManager::GetInstance().AddService(std::move(service_)); //(1)} } 在注释1处EndSection()函数调用了ServiceManager的AddService函数;system/core/init/service.cpp void ServiceManager::AddService(std::unique_ptrService service) {Service* old_service FindServiceByName(service-name());if (old_service) {LOG(ERROR) ignored duplicate definition of service service-name() ;return;}services_.emplace_back(std::move(service)); //1 } 在AddService函数中首先根据服务名判断该服务old_service是否已经存在如果不存在则在注释1中将Service对象加入Service链表。4.4在init进程中启动Zygote进程 我们回到init.rc文件中有如下代码system/core/rootdir/init.rc...... on nonencryptedclass_start main //(1)class_start late_start ...... 注释1中的class_start是一个command命令意思为启动classname为main的Service。在上面的4.2中提到的init.zygote64.rc里面是service语句其中描述里面说明了service的classname为main所以这里的class_start main就是启动zygote进程的。 class_start 命令所对应的函数为do_class_start(),该函数的位置在system/core/init/builtins.cpp中。system/core/init/builtins.cppstatic int do_class_start(const std::vectorstd::string args) {/* Starting a class does not start services* which are explicitly disabled. They must* be started individually.*/ServiceManager::GetInstance().ForEachServiceInClass(args[1], [] (Service* s) { s-StartIfNotDisabled(); }); //(1)return 0; } 在注释1处我们看到调用了ForEachServiceInClass函数对于这里对c语言不熟悉的可能看不太懂我稍微解释一下。ForEachServiceInClass函数里面传入了两个参数一个是”args[1]“另一个是“ [] (Service* s) { s-StartIfNotDisabled(); }”对于第二个参数这里使用了Lambda函数的写法也就是匿名函数也可以称为临时函数所谓临时函数顾名思义就是在某一次临时使用Lambda表达式可作为一个对象然后可把它作为参数传递相当于把“[] (Service* s) { s-StartIfNotDisabled(); }”作为一个参数传入到ForEachServiceInClass(函数中其中这个匿名函数的实现体会进行调用Service的StartIfNotDisabled()函数的操作。 接下来我们来看一下StartIfNotDisabled()函数实现了什么操作system/core/init/service.cppbool Service::StartIfNotDisabled() {if (!(flags_ SVC_DISABLED)) { //(1)return Start(); //(2)} else {flags_ | SVC_DISABLED_START;}return true; } 首先会在注释1处判断前面提到的init.zygote64.rc是否又设置disabled如果没有设置则调用system/core/init/service.cpp里面的Start()函数。 接下来我们来查看一下Start()函数里面进行了什么操作system/core/init/service.cppbool Service::Start() {// Starting a service removes it from the disabled or reset state and// immediately takes it out of the restarting state if it was in there.flags_ (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));// Running processes require no additional work --- if theyre in the// process of exiting, weve ensured that they will immediately restart// on exit, unless they are ONESHOT.if (flags_ SVC_RUNNING) { //1return false;}bool needs_console (flags_ SVC_CONSOLE);if (needs_console) {if (console_.empty()) {console_ default_console;}// Make sure that open call succeeds to ensure a console driver is// properly registered for the device nodeint console_fd open(console_.c_str(), O_RDWR | O_CLOEXEC);if (console_fd 0) { //2PLOG(ERROR) service name_ couldnt open console console_ ;flags_ | SVC_DISABLED;return false;}close(console_fd);}......LOG(INFO) starting service name_ ...;pid_t pid -1;if (namespace_flags_) {pid clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);} else {pid fork(); //(3)}if (pid 0) { //4umask(077);......std::vectorchar* strs;ExpandArgs(args_, strs);if (execve(strs[0], (char**) strs[0], (char**) ENV) 0) { //(5)PLOG(ERROR) cannot execve( strs[0] );}_exit(127);}......return true; } 在以上的注释1判断service是否已经运行了如果已经在运行了则不需要重新启动了在注释2处是一些驱动打开准备工作如果没有正常打开则不启动service。 如果经过前面代码的判断和准备工作均完成了即会走到了注释3处调用fork函数创建子进程且得到pid值在4处判断pid是否为0为0则说明当前代码正在子进程里面运行。 在注释(5)处子进程里调用了execve函数Service被启动并进入service的main函数中如果该service是zygote根据前面4.2提到的init.zygote64.rc文件里面的内容根据里面的service语句zygote的执行程序的路径是/system/bin/app_process64可以使用adb连接上调试机或者模拟的Android机在/system/bin目录下有app_process64这个可执行程序截图如下 而app_process64这个可执行程序所对应的代码文件路径为frameworks/base/cmds/app_process/app_main.cpp,该程序启动后会进入app_main.cpp的main函数中也就是zygote的main()函数下面我们来看看main函数frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { ......// --zygote : Start in zygote mode// --start-system-server : Start the system server.// --application : Start in application (stand alone, non zygote) mode.// --nice-name : The nice name for this process.......bool zygote false; //(1)bool startSystemServer false; //(2)bool application false; //(3)String8 niceName;String8 className;i; while (i argc) {const char* arg argv[i];if (strcmp(arg, --zygote) 0) {zygote true; //(4)niceName ZYGOTE_NICE_NAME;} else if (strcmp(arg, --start-system-server) 0) {startSystemServer true;} else if (strcmp(arg, --application) 0) {application true;} else if (strncmp(arg, --nice-name, 12) 0) {niceName.setTo(arg 12);} else if (strncmp(arg, --, 2) ! 0) {className.setTo(arg);break;} else {--i;break;}}......if (zygote) {runtime.start(com.android.internal.os.ZygoteInit, args, zygote); //(5)} else if (className) {runtime.start(com.android.internal.os.RuntimeInit, args, zygote);} else {fprintf(stderr, Error: no class name or --zygote supplied.\n);app_usage();LOG_ALWAYS_FATAL(app_process: no class name or --zygote supplied.);} } 在注释1、2、3中分别声明了三个布尔型的变量用来标记当前在什么进程中运行如注释4中若通过strcmp(函数判断arg参数的值为--zygote说明当前在zygote进程中则将标记zygote设置为true。在注释5处标记zygote为true则调用AppRuntime的start函数启动zygote关于zygote的更详细的讲解我将会放到第5节进行讲解。4.5 init进程对属性的初始化 现在回到4.1展示的init进程的main的代码system/core/init/init.cpp其中标记的注释1处调用了property_init函数在标记3处调用了 start_property_service()函数system/core/init/init.cppint main(int argc, char** argv) {......property_init(); //(1)......start_property_service(); //(3)......} 在property_init()的函数里面对系统属性进行初始化这些属性也就是我们平时开发的时候通过adb shell getprop命令获取到一系列系统参数。 我们先查看一下property_init()函数void property_init() {if (__system_property_area_init()) {LOG(ERROR) Failed to initialize property area;exit(1);} }__system_property_area_init()函数用来初始化属性的内存区域。 start_property_service()函数的代码如下void start_property_service() {property_set(ro.property_service.version, 2);property_set_fd create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,0666, 0, 0, NULL); //1if (property_set_fd -1) {PLOG(ERROR) start_property_service socket creation failed;exit(1);}listen(property_set_fd, 8); //2register_epoll_handler(property_set_fd, handle_property_set_fd); //3 } 从代码可以看到在start_property_service函数里注释1处开启了一个socket(套接字)用来等待客户端的属性请求在注释2处进行监听且在注释3处给开启的服务设置相对应的处理函数handle_property_set_fd当服务property_set_fd接收到了客户端对系统属性值的修改请求时就会调用handle_property_set_fd函数进行处理。4.6 init进程操作总结 根据以上的几点介绍我们知道init进程的主要操作流程如下Zygote进程 5.1 zygote的执行程序app_process 在4.4节里我们提到在frameworks/base/cmds/app_process/app_main.cpp里调用了AppRuntime的start函数启动zygote。frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { ......// --zygote : Start in zygote mode// --start-system-server : Start the system server.// --application : Start in application (stand alone, non zygote) mode.// --nice-name : The nice name for this process.......bool zygote false; //(1)bool startSystemServer false; //(2)bool application false; //(3)String8 niceName;String8 className;i; while (i argc) {const char* arg argv[i];if (strcmp(arg, --zygote) 0) {zygote true; //(4)niceName ZYGOTE_NICE_NAME;} else if (strcmp(arg, --start-system-server) 0) {startSystemServer true;} else if (strcmp(arg, --application) 0) {application true;} else if (strncmp(arg, --nice-name, 12) 0) {niceName.setTo(arg 12);} else if (strncmp(arg, --, 2) ! 0) {className.setTo(arg);break;} else {--i;break;}}......if (zygote) {runtime.start(com.android.internal.os.ZygoteInit, args, zygote); //(5)} else if (className) {runtime.start(com.android.internal.os.RuntimeInit, args, zygote);} else {fprintf(stderr, Error: no class name or --zygote supplied.\n);app_usage();LOG_ALWAYS_FATAL(app_process: no class name or --zygote supplied.);} } 之前我们提到在注释1、2、3中分别声明了三个布尔型的变量用来标记当前在什么进程中运行。因为到后面zygote进程会通多fork函数进行复制创建各种其他进程的。例如后面将要提到的systemservicer以及应用程序进程都是通过zygote进程进行复制出来的创建之后都会走main函数里的代码逻辑因此在这里声明了几个标志位用来判断当前是在什么进程里运行。 在注释5里调用了AppRuntime的start函数启动zygote我们来查看一下start()函数的内容frameworks/base/core/jin/AndroidRuntime.cpp/** Start the Android runtime. This involves starting the virtual machine* and calling the static void main(String[] args) method in the class* named by className.** Passes the main function two arguments, the class name and the specified* options string.*/ void AndroidRuntime::start(const char* className, const VectorString8 options, bool zygote) {....../* start the virtual machine */JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(mJavaVM, env, zygote) ! 0) { //1return;}onVmCreated(env);/** Register android functions.*/if (startReg(env) 0) { //2ALOGE(Unable to register all android natives\n);return;}....../** Start VM. This thread becomes the main thread of the VM, and will* not return until the VM exits.*/char* slashClassName toSlashClassName(className); //3jclass startClass env-FindClass(slashClassName);//(4)if (startClass NULL) {ALOGE(JavaVM unable to locate class %s\n, slashClassName);/* keep going */} else {jmethodID startMeth env-GetStaticMethodID(startClass, main,([Ljava/lang/String;)V);//(5)if (startMeth NULL) {ALOGE(JavaVM unable to find main() in %s\n, className);/* keep going */} else {env-CallStaticVoidMethod(startClass, startMeth, strArray);//6#if 0if (env-ExceptionCheck())threadExitUncaughtException(env); #endif}}free(slashClassName);ALOGD(Shutting down VM\n);if (mJavaVM-DetachCurrentThread() ! JNI_OK)ALOGW(Warning: unable to detach main thread\n);if (mJavaVM-DestroyJavaVM() ! 0)ALOGW(Warning: VM did not shut down cleanly\n); } 在注释有1处调用了startVm函数来创建java虚拟机注释2处调用startReg函数为java虚拟机注册jni方法。注释3处调用的toSlashClassName()函数很简单即将className中的“.”替换成“/”。根据4.4里app_main.cpp里面调用的方法“runtime.start(com.android.internal.os.ZygoteInit, args, zygote); 我们可以知道className的值为com.android.internal.os.ZygoteInit因此可知slashClassName的值为”com/android/internal/os/ZygoteInit“,注释4处通过这个slashClassName这个路径找到ZygoteInit类并且将这个类赋值给slashClass,在注释5通过方法名”main“找到ZygoteInit类的main方法最后在注释6处使用类名、方法名通过JNI方式调用ZygoteInit类的main方法。 此时就已经从Native层进入了java框架层对JNI调用不熟悉的同学可自行查询资料。 5.2 java框架层的ZygoteInit 我们来看一下ZygoteInit类中的main()方法frameworks/base/core/java/com/android/internal/os/ZygoteInitpublic static void main(String argv[]) {ZygoteServer zygoteServer new ZygoteServer();........zygoteServer.registerServerSocket(socketName); //(1)......if (startSystemServer) {startSystemServer(abiList, socketName, zygoteServer); //(2)}Log.i(TAG, Accepting command socket connections);zygoteServer.runSelectLoop(abiList); //(3)zygoteServer.closeServerSocket();} catch (Zygote.MethodAndArgsCaller caller) {caller.run();} catch (Throwable ex) {Log.e(TAG, System zygote died with exception, ex);zygoteServer.closeServerSocket();throw ex;}}注释1处可以看到main()方法里面通过registerServerSocket方法创建一个Server端的套接字Socket这个服务是用来等待ActivityManagerServiceAMS的创建新应用程序进程的请求的在注释2启动了SystemServer系统服务进程在注释3处调用了runSelectLoop方法便开始等待AMS的请求了。 接下来我们看一下这三个注释分别做了什么。5.2.1 registerZygoteSocketframeworks/base/core/java/com/android/internal/os/ZygoteServer.javavoid registerServerSocket(String socketName) {if (mServerSocket null) {int fileDesc;final String fullSocketName ANDROID_SOCKET_PREFIX socketName;try {String env System.getenv(fullSocketName);fileDesc Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException(fullSocketName unset or invalid, ex);}try {FileDescriptor fd new FileDescriptor();fd.setInt$(fileDesc);mServerSocket new LocalServerSocket(fd); //(1)} catch (IOException ex) {throw new RuntimeException(Error binding to local socket fileDesc , ex);}}}注释1处创建了服务端的Socket套接字。5.2.2 startSystemServerframeworks/base/core/java/com/android/internal/os/ZygoteInit private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)throws Zygote.MethodAndArgsCaller, RuntimeException {....../* Hardcoded command line to start the system server */String args[] { //(1)--setuid1000,--setgid1000,--setgroups1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010,--capabilities capabilities , capabilities,--nice-namesystem_server,--runtime-args,com.android.server.SystemServer,};ZygoteConnection.Arguments parsedArgs null;int pid;try {parsedArgs new ZygoteConnection.Arguments(args); //(2)ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);/* Request to fork the system server process */pid Zygote.forkSystemServer( //(3)parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}/* For child process */if (pid 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}zygoteServer.closeServerSocket();handleSystemServerProcess(parsedArgs); //(4)}return true;} 注释1处创建了一个数组数组中包含uid,gid等uid的和gid的值都为1000且数组中的com.android.server.SystemServer值说明启动的类名为com.android.server.SystemServer。在注释2处将该数组封装成ZygoteConnection.Arguments类型的实例。注释3调用了forkSystemServer方法并且将封装的Arguments实例的成员值传入。forkSystemServer方法里会通过JNI调用Native的NativenativeForkSystemServer方法。而NativenativeForkSystemServer方法最后会调用fork函数创建一个子进程该子进程也就是SystemServer进程。在注释4处如果pid为0即表示当前代码运行在新创建的子进程中会调用handleSystemServerProcess来处理SystemServer进程。5.2.3 runSelectLoop 在5.2的注释3中调用了zygoteServer.runSelectLoop函数我们来看一下runSelectLoop函数函数frameworks/base/core/java/com/android/internal/os/ZygoteServer.java void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {ArrayListFileDescriptor fds new ArrayListFileDescriptor();ArrayListZygoteConnection peers new ArrayListZygoteConnection();fds.add(mServerSocket.getFileDescriptor());peers.add(null);while (true) { //1StructPollfd[] pollFds new StructPollfd[fds.size()];for (int i 0; i pollFds.length; i) {pollFds[i] new StructPollfd();pollFds[i].fd fds.get(i);pollFds[i].events (short) POLLIN;}try {Os.poll(pollFds, -1);} catch (ErrnoException ex) {throw new RuntimeException(poll failed, ex);}for (int i pollFds.length - 1; i 0; --i) { //(2)if ((pollFds[i].revents POLLIN) 0) {continue;}if (i 0) { //2ZygoteConnection newPeer acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else { //(3)boolean done peers.get(i).runOnce(this);if (done) {peers.remove(i);fds.remove(i);}}}}} 注释1表明无限循环等待AMS的请求。在注释2处i初始化为pollFds里的数据个数如果pollFds里面有数据即不为0则走到注释3处调用runOnce(方法创建一个新的应用程序进程创建成功了之后就将该相关的创建请求从连接列表里清除。5.3 Zygote进程总结1调用了AppRuntime的start方法启动Zygote进程2创建java虚拟机且为其注册JNI方法3通过JNI调用ZygoteInit的main()方法此时从native进入了java框架4创建服务器端socket5启动systemserver进程6使服务器端socket循环等待等待AMS的创建新的应用程序进程的请求6. SystemServer进程 SystemServer系统服务主要是用来拆功能键系统服务的AMS、WMS以及PMS都是由它创建的。 接下来我们来看一下zygoteInit是如何启动SystemServer进程的。6.1 Zygote调用startSystemServer 在5.2.2我们看到ZygoteInit调用了startSystemServer方法启动了SystemServer,我们来看一下这个过程做了什么处理frameworks/base/core/java/com/android/internal/os/ZygoteInit private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)throws Zygote.MethodAndArgsCaller, RuntimeException {......pid Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}/* For child process */if (pid 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}zygoteServer.closeServerSocket();handleSystemServerProcess(parsedArgs); //(1)}return true;} 在5.2.2中我们看到启动服务的相关参数存在数组里而这个数组封装到parsedArgs中注释1调用handleSystemServerProcess()方法且将parsedArgs参数传给handleSystemServerProcess()handleSystemServerProcess()方法如下所示frameworks/base/core/java/com/android/internal/os/ZygoteInit /*** Finish remaining work for the newly forked system server process.*/private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws Zygote.MethodAndArgsCaller {......ClassLoader cl null;if (systemServerClasspath ! null) {cl createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);Thread.currentThread().setContextClassLoader(cl);}/** Pass the remaining arguments to SystemServer.*/ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//(1)}} 注释1处调用了ZygoteInit的zygoteInit方法zygoteInit方法如下所示frameworks/base/core/java/com/android/internal/os/ZygoteInit public static final void zygoteInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {if (RuntimeInit.DEBUG) {Slog.d(RuntimeInit.TAG, RuntimeInit: Starting application from zygote);}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ZygoteInit);RuntimeInit.redirectLogStreams();RuntimeInit.commonInit();ZygoteInit.nativeZygoteInit(); //1RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//2}在注释1处调用了native层的函数nativeZygoteInit该方法时用来启动Binder线程池的通过该线程池SystemServer进程就可以和其他进程进行通信了。注释2处是调用SystemServer的main方法。下面来看一下注释1和注释2的方法。6.1.1 nativeZygoteInit 前面我们提到nativeZygoteInit是native层的一个方法那么这个方法是否就是底层里的nativeZygoteInit其实并不是对于这个名字java层和native层并不是一一对应的那么我们如何确定调用了native层的哪一个方法呢此时 我们需要了解它对应的JNI 文件。frameworks/base/core/jni/AndroidRuntime.cppint register_com_android_internal_os_ZygoteInit(JNIEnv* env) {const JNINativeMethod methods[] { //(1){ nativeZygoteInit, ()V,(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },};return jniRegisterNativeMethods(env, com/android/internal/os/ZygoteInit,methods, NELEM(methods)); //(2) } 对应的jni代码在frameworks/base/core/jni/AndroidRuntime.cpp在看看注释2处已经将com/android/internal/os/ZygoteInit注册而注释1里的数组里面看到对应的nativeZygoteInit方法是com_android_internal_os_ZygoteInit_nativeZygoteInitcom_android_internal_os_ZygoteInit_nativeZygoteInit方法如下frameworks/base/core/jni/AndroidRuntime.cppstatic void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz) {gCurRuntime-onZygoteInit();//1 } 注释1处的gCurRuntime函数指向的是AndroidRuntime的子项AppRuntime接下来我们看一下onZygoteInit()函数该函数的位置在framework/base/cmds/app_main.cppframework/base/cmds/app_main.cpp virtual void onZygoteInit(){spProcessState proc ProcessState::self();ALOGV(App process: starting thread pool.\n);proc-startThreadPool(); //1} 可以看到在注释1处这里开启了线程池此时SystemServer进程就可以通过该Binder线程池和其他进程进行通行了。6.1.2 applicationInit 6.1中的注释2处调用了RuntimeInit的applicationInit方法接下来我们查看一下该方法:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws Zygote.MethodAndArgsCaller {......invokeStaticMain(args.startClass, args.startArgs, classLoader);//(1)} 注释1处调用了invokeStaticMain方法frameworks/base/core/java/com/android/internal/os/RuntimeInit.java private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws Zygote.MethodAndArgsCaller {Class? cl;try {cl Class.forName(className, true, classLoader); //1} 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 }); //2} catch (NoSuchMethodException ex) {throw new RuntimeException(Missing static main on className, ex);} catch (SecurityException ex) {throw new RuntimeException(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);}/** This throw gets caught in ZygoteInit.main(), which responds* by invoking the exceptions run() method. This arrangement* clears up all the stack frames that were required in setting* up the process.*/throw new Zygote.MethodAndArgsCaller(m, argv); //3} 在注释1处通过反射得到SystemServer类注释2处找到SystemServer类的main方法而在注释3处将该main()方法m传给Zygote.MethodAndArgsCaller然后抛出异常该异常会向上抛给ZygoteInit.java的main方法中的try/catch语句捕获为什么要将该方法向上抛出给会ZygoteInit然后在ZygoteInit.java的main方法中捕获到然后再调用SystemServer类的main方法呢而不是直接在这里调用SystemServer类的main方法呢这里源码有中就有解释因为在这调用SystemServer类的main方法之前就对SystemServer类有很多初始化的操作产生了很多栈缓存因此使用这种抛出异常的方式可以将这些缓存清除掉。接下来我们来看一下捕获到了异常之后进行了什么操作frameworks/base/core/java/com/android/internal/os/ZygoteInit public static void main(String argv[]) {........} catch (Zygote.MethodAndArgsCaller caller) {caller.run(); //1} catch (Throwable ex) {Log.e(TAG, System zygote died with exception, ex);zygoteServer.closeServerSocket();throw ex;}} 在注释1处捕获到了抛出的异常之后就调用了Zygote.MethodAndArgsCaller的run()方法frameworks/base/core/java/com/android/internal/os/Zygote.java public static class MethodAndArgsCaller extends Exceptionimplements Runnable {/** method to call */private final Method mMethod;/** argument array */private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod method; //(1)mArgs args;}public void run() {try {mMethod.invoke(null, new Object[] { mArgs }); //(2)} 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);}}}我们可以看到注释1处的mMethod是传经来的SystemServer的main方法因此注释2便是启用并进入了SystemServer的main方法了。6.2 SystemServer进程 SystemServer的main方法frameworks/base/services/java/com/android/server/SystemServer.java /*** The main entry point from zygote.*/public static void main(String[] args) {new SystemServer().run();//(1)} 这里只有一句代码调用了SystemServer的run方法frameworks/base/services/java/com/android/server/SystemServer.java private void run() {try {......// Initialize native services.System.loadLibrary(android_servers); //(1)// Check whether we failed to shut down last time we tried.// This call may not return.performPendingShutdown();// Initialize the system context.createSystemContext(); //(2)// Create the system service manager.mSystemServiceManager new SystemServiceManager(mSystemContext); //(3)mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.get();} finally {traceEnd(); // InitBeforeStartServices} // Start services.try {traceBeginAndSlog(StartServices);startBootstrapServices(); //(4)startCoreServices(); //(5)startOtherServices(); //(6)SystemServerInitThreadPool.shutdown();} catch (Throwable ex) {Slog.e(System, ******************************************);Slog.e(System, ************ Failure starting system services, ex);throw ex;} .......} 在注释1处架子啊了动态库libandroid_servers.so,在注释2处创建了系统context在注释3处创建了SystemServiceManager,SystemServiceManager将会对一系列的系统服务进行管理。注释4、5、6分别启动了三类服务分别是引导服务、核心服务、其他服务。引导服务有ActivityManagerService、PowerManagerService、PackageManagerService等核心服务有DropBoxManagerService、BatteryService、UsageStatsService等其他服务有CameraService、AlarmManagerService等。这些所有的服务的父类都为SystemService。frameworks/base/services/java/com/android/server/SystemServer.java private void startBootstrapServices() {......// Power manager needs to be started early because other services need it.// Native daemons may be watching for it to be registered so it must be ready// to handle incoming binder calls immediately (including being able to verify// the permissions for those calls).traceBeginAndSlog(StartPowerManager);mPowerManagerService mSystemServiceManager.startService(PowerManagerService.class);//1......mSystemServiceManager.startService(RecoverySystemService.class);//2......mSystemServiceManager.startService(LightsService.class);//3...... } 这里的注释1、2、3等都是调用了SystemServiceManager的startService方法启动了一些服务startBootstrapServices方法启动了很多服务我这里没有将所有的启动剩余服务的部分代码一一展示出来。调用的startService()方法如下frameworks/base/services/core/java/com/android/server/SystemServeManager.java public void startService(NonNull final SystemService service) {// Register it.mServices.add(service); //1// Start it.long time System.currentTimeMillis();try {service.onStart(); //2} catch (RuntimeException ex) {throw new RuntimeException(Failed to start service service.getClass().getName() : onStart threw an exception, ex);}warnIfTooLong(System.currentTimeMillis() - time, service, onStart);} 在注释1中首先将需要启动的系统服务添加到系统服务列表里然后在注释2处调用服务的onStart方法启动服务。6.3 SystemServer进程总结1启动Binder线程池2创建SystemServiceManager3启动系统各种服务7.Launcher 由于篇幅过长launcher的详细启动流程暂时不在这篇文章里详细描述。我将会在下一篇文章里面说明感兴趣的同学可以关注一下。 在前面我们较详细的把init进程、Zygote进程以及SystemServer进程的启动流程中主要进行的操作梳理了一遍这些可以说是Android操作启动到呈现主页给用户的准备工做直到Launcher也就是将主页界面展示给大家Android操作系统就启动完成了。8.总结 我们在前面将Android系统启动做的主要工作都展示出来了必要的地方也将代码贴出来了但是我们阅读源码的时候就发现其实这个过程做的工作远远比我上面提到的要多我这里只是将“主线”贴出来了如果需要更加详细的了解各个细节同学们可以自行查阅源码深究。总的流程如下电源启动BootLoader引导程序Linux内核启动init进程启动Zygote进程启动SystemServer进程的启动启动Launcher
http://www.hkea.cn/news/14521926/

相关文章:

  • 毕节建设局网站html解析wordpress
  • 虚拟主机怎么发布网站贵阳网站建设包首页
  • dw软件做网站哪些网站可以做视频搬运
  • 海口建站模板网站建设和推广的完整话术
  • 国外产品展示网站源码广州各区风险区域最新动态
  • 国内企业网站模板微微营销
  • 欧美做视频网站有哪些网页设计面试自我介绍
  • 建站步骤图视频做网站背景
  • 网上接网站项目宁波比较好的外贸公司
  • 别人网站的字体付费阅读小说网站开发建设源码
  • 安徽建设银行网站哈尔滨电商设计企业
  • 阜蒙县自治区建设学校网站绵阳seo
  • 济南市建设工程招标投标协会网站网站平台建设要多久
  • 佛山如何网站建设在哪里做wordpress没有页脚选项
  • 长沙h5手机网站制作网站上的菠菜游戏哪里可以做
  • 电商网站分析报告网页制作软件dw还需要什么
  • 怎么搭建手机网站m聚豪云免费虚拟主机
  • 金蝶直播wordpress模板优化
  • 站长工具seo推广xampp wordpress 建站教程
  • 不屏蔽网站的浏览器福建省建设干部网站
  • php网站开发工资多少钱wordpress固定链接怎么设置
  • 建网站做seo微信二维码在线制作
  • 品牌网站建设搜搜磐石网络成都个人网站制作公司
  • 临沂市建设局网站勘察设计如何做自己的网站或者论坛
  • 写作网站六大神书免费网页申请
  • 做动画网站去哪采集绵阳东原建设工程有限公司网站
  • 阜阳网站建设价格低网站建设的经营范围
  • 有哪些官方网站做的比较好昆山网站建设义搏
  • 宜昌市建设厅官方网站安庆集团网站建设
  • 网站后台管理图片水印怎么做网页设计与制作难不难