比较windows phone程序启动和android程序启动原理

摘要:
Windows phone程序是如何启动的?它和Android程序有什么区别?我们专注于在Windows phone程序启动时从本机代码级别进行分析:使用应用程序定义指定XAML中的起始页。当WindowsPhone7APP启动时,它将自动导航到HomePage.xaml并显示文件。以下是android从服务管理器启动相应的后台进程,并使用zyngote启动守护进程。至于守护进程在java中的应用,有很多应用。例如,当您使用apache发布jsp程序时,这个apache就是守护进程。最后一系列onstart关键字表示当合子进程重新启动时要执行的命令。

 windows phone 程序是如何启动的了,他和android程序有什么区别,我们重点从native code 层面来分析

 在windows phone 程序启动的时候是:

在XAML中使用应用程序定义指定起始Page(它是启动 WindowsPhone7程序时自动加载的Page)。
  指定方法是将 StartupUri 属性设置为所需的 Page 的 统一资源标识符 (URI)。
  可以在标记中以声明方式设置 StartupUri,如下面的示例所示。
<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    StartupUri="PageWithHyperlink.xaml" />
  此例中,StartupUri 特性设置为标识 HomePage.xaml 的相对 pack URI。当WindowsPhone7 APP 启动时,将自动导航到 HomePage.xaml 并显示该文件。就是这个鸟样:

比较windows phone程序启动和android程序启动原理第1张

至于android是如何启动的,我这里要从native code 讲起来。

首先,大家都知道android是linux内核的,他的启动自然离不开linux中的boothloader与kernel启动,这里面我就不做过多的赘述。

下面都是android的从servicemanager里面来启动相应的后台进程,用zyngote来启动daemon process。这个后台进程是用来使其程序得以维持,而daemon 这个守护进程是对程序的状况得以监听的。至于daemon process 在java上的应用确实很多,譬如用apache 发布jsp的程序的时候,这个apache就是守护进程。

 servicemanager这是c语言中定义,定义中的后台的进程,至于zynote这个进程了,这是从app_main cp中来开启一个initial方法对其初始化方法。

前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。

 接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。

        最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。

        关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。

        了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。在继续分析Zygote进程启动的过程之前,我们先来看看它的启动序列图:

比较windows phone程序启动和android程序启动原理第2张

 这是app_ain中的cpp源代码:

int main(int argc, const char* const argv[])  
{  
    // These are global variables in ProcessState.cpp   
    mArgC = argc;  
    mArgV = argv;  
  
    mArgLen = 0;  
    for (int i=0; i<argc; i++) {  
        mArgLen += strlen(argv[i]) + 1;  
    }  
    mArgLen--;  
  
    AppRuntime runtime;  
    const char *arg;  
    argv0 = argv[0];  
  
    // Process command line arguments   
    // ignore argv[0]   
    argc--;  
    argv++;  
  
    // Everything up to '--' or first non '-' arg goes to the vm   
  
    int i = runtime.addVmArguments(argc, argv);  
  
    // Next arg is parent directory   
    if (i < argc) {  
        runtime.mParentDir = argv[i++];  
    }  
  
    // Next arg is startup classname or "--zygote"   
    if (i < argc) {  
        arg = argv[i++];  
        if (0 == strcmp("--zygote", arg)) {  
            bool startSystemServer = (i < argc) ?  
                strcmp(argv[i], "--start-system-server") == 0 : false;  
            setArgv0(argv0, "zygote");  
            set_process_name("zygote");  
            runtime.start("com.android.internal.os.ZygoteInit",  
                startSystemServer);  
        } else {  
            set_process_name(argv0);  
  
            runtime.mClassName = arg;  
  
            // Remainder of args get passed to startup class main()   
            runtime.mArgC = argc-i;  
            runtime.mArgV = argv+i;  
  
            LOGV("App process is starting with pid=%d, class=%s.
",  
                getpid(), runtime.getClassName());  
            runtime.start();  
        }  
    } else {  
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");  
        fprintf(stderr, "Error: no class name or --zygote supplied.
");  
        app_usage();  
        return 10;  
    }  
  
}  

我们惊奇的看到了start了zynote.cs 文件,   这个就是开启了zynote进程,这个就是当前守护进程的初始化。那么这个zynote.cpp是什么了?
我们看其中AndroidRuntime的源代码:

  1. ......  
  2.   
  3. static AndroidRuntime* gCurRuntime = NULL;  
  4.   
  5. ......  
  6.   
  7. AndroidRuntime::AndroidRuntime()  
  8. {  
  9.     ......  
  10.   
  11.     assert(gCurRuntime == NULL);        // one per process   
  12.     gCurRuntime = this;  
  13. }  

这个androidRunTime,是cpp文件, 是通过jnt方式用java来访问c++的源代码,这是android能够调用linux kernel中的关键性的技术。

这就是我对android 中的启动理解。

   这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。

 它主要作了三件事情,一个调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯,二是调用startSystemServer函数来启动SystemServer组件,三是调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。

这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,它定义为:

        那么,这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释init.rc文件中的service命令的:

每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去:

       因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了,参考4,ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而Process类是通过openZygoteSocketIfNeeded函数来连接到Zygote进程中的Socket的:

这是我对android理解,这能够对大家带来帮助。

好好学习,天天向上。

免责声明:文章转载自《比较windows phone程序启动和android程序启动原理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇git学习简单操作三层架构+存储过程实现分页下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

《ArcGIS Runtime SDK for Android开发笔记》——问题集:Error:Error: File path too long on Windows, keep below 240 characters

1、前言 在使用Android Studio开发环境时,经常会爆出以下错误,虽然具体细节内容各有不同,但是说明的都是同一个问题,在windows中使用过长的路径,超过240字符。 Error:Error: File path too long on Windows, keep below 240 characters : C:UsersadminWork3...

SOAP、SOCKET协议

一、SOAP( SOAP:Simple Object Access Protocol) 简单对象访问协议,简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议( HTTP),简单邮件传输协议(SMTP),多用途网际邮件...

在Express和Socket.IO中使用session

在Express和Socket.IO中使用session_三水清 在Express和Socket.IO中使用session 在nodejs项目中对于一些认证需要用到session,例如我写的nodejs 聊天室的demo,就是通过session实现的认证。当存在session,直接进入聊天室,而不会重新登录。 在网上也找到不少关于Express框架中的...

raw_socket(原始套接字)以及普通socket使用终极总结

  一、传输层socket(四层socket,普通socket) 可参考本人以下博客: Windows Socket编程之UDP实现大文件的传输:http://blog.csdn.net/luchengtao11/article/details/71016222 Windows Socket编程之TCP实现大文件的传输:http://blog.csd...

Linux操作临时文件

使用临时文件要考虑几个问题: 保证临时文件间的文件名不互助冲突。 保证临时文件中内容不被其他用户或者黑客偷看、删除和修改。 Linux中提供了mkstemp 和 tmpfile 函数来处理临时文件。 mkstemp函数 int mkstemp(char *template); mkstemp函数在系统中以唯一的文件名创建一个文件并打开,而且只有当前用户...

LINUX共享内存使用常见陷阱与分析【转】

转自:https://blog.csdn.net/sweetfather/article/details/80006161 所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。其他进程能把同一段共享内存段“连接到”他们自己的地址空...