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

小学网站建设情况汇报西安 做网站

小学网站建设情况汇报,西安 做网站,网站建设费怎么入分录,个人可以注册商标吗目录 Android 系统启动流程 init 进程分析 init.rc 解析 Zygote 概叙 Zygote 触发过程 Zygote 启动过程 什么时Runtime#xff1f; System Server 启动流程 Fork 函数 总结 面试题 Android 是 google 公司开发的一款基于 Linux 的开源操作系统。 Android 系统启动…目录 Android 系统启动流程 init 进程分析 init.rc 解析 Zygote 概叙 Zygote 触发过程 Zygote 启动过程 什么时Runtime System Server 启动流程 Fork 函数 总结 面试题 Android 是 google 公司开发的一款基于 Linux 的开源操作系统。 Android 系统启动流程 android 系统启动的大概流程如下图所示 第一步启动电源以及系统启动 当电源按下引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到 RAM然后执行。 第二步引导程序 引导程序是在 Android 操作系统开始运行前的一个小程序。引导程序是运行的第一个程序因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如 reboot, uboot, qibootloader 或者开发自己的引导程序它不是 Android 操作系统的一部分。引导程序是 OEM 厂商或者运营商加锁和限制的地方。 引导程序分两个阶段执行 第一阶段检测外部的RAM以及加载第二阶段有用的程序。 第二阶段引导程序设置网络、内存等等。这些对于运行内核是必须的为了达到特殊的目标引导程序可以根据配置参数或者输入数据设置内核。 Android 引导程序可以在 \bootable\bootloader\regacy\usbloader 找到。传统的加载器包含两个文件需要在这里说明 init.s 初始化堆栈清零 BBS 段调用 main.c 的 main()  函数 main.c 初始化硬件(闹钟、主板、键盘、控制台) 创建 linux 标签 第三步内核(Kernel) Android 内核与桌面 linux 内核启动方式差不多。内核启动时设置缓存、保护存储器、计划列表、加载驱动。当内核完成系统设置它首先在系统文件种寻找 init 文件然后启动 root 进程或者系统的第一个进程。 第四步init 进程 init 进程是 Linux 系统中用户空间的第一个进程进程号固定为1。Kernel 启动后在用户空间启动 init 进程并调用 init 中的 main() 方法执行 init 进程的职责。 第五步启动 Lancher App init 进程分析 其中 init 进程是 Android 系统中及其重要的第一个进程init 进程做了如下三件事 1. 创建和挂载启动所需要的文件目录 2. 初始化和启动属性服务 3. 解析 init.rc 配置文件并启动 zygote 进程 init.rc 解析 init.rc 是一个非常重要的配置文件它是由 Android 初始化语言(Android Init Language) 编写的脚本它主要包含五种类型语句Action(Action 中包含了一系列的 Command)、Commands(init 语言中的命令)、Services(由 init 进程启动的服务)、Options(对服务进行配置的选项) 和 Import (导入其它配置文件)。init.rc 的配置代码如下所示 # \system\core\rootdir\init.rc on init # L41 sysclktz 0 # Mix device-specific information into the entropy pool copy /proc/cmdline /dev/urandom copy /default.prop /dev/urandom ... on trigger [ trigger]* //设置触发器 command command //动作触发之后要执行的命令 service name pathname [ argument ]* //service的名字执行程序路径传递参 数 option //Options是Services的参数配置. 它们影响Service如何运行及运行时机 group groupname [ groupname\* ] //在启动Service前将group改为第一个 groupname,第一个groupname是必须有的 //默认值为root或许默认值是无第二个groupname可以不设置用于追加组通过 setgroups priority priority //设置进程优先级. 在-2019之间默认值是0,能过 setpriority实现 socket name type perm [ user [ group [ seclabel ] ] ]//创建 一个unix域的socket,名字叫/dev/socket/name , 并将fd返回给Service. type 只能是 dgram, stream or seqpacket. ... Action Action: 通过触发器 trigger即以 on 开头的语句来决定执行相应的 service 的时机 on early-init: 在初始化早期阶段触发 on init: 在初始化阶段触发 on late-init: 在初始化晚期阶段触发 on boot/charger: 当系统启动/充电时触发 on property: 当属性值满足条件时触发。 Service 服务 Service以 service 开头由 init 进程启动一般运行在 init 的一个子进程所以启动 service 前需要判断对应的可执行文件是否存在。init 生成的子进程定义在 rc 文件其中每一个 service 在启动时会通过 fork 方式生成子进程。 例如service servicemanager /system/bin/servicemanager 代表的是服务名为 servicemanager服务执行的路径为 /system/bin/servicemanager。 Command 下面列举常用的命令 class_startservice_class_name: 启动属于同一个 class 的所有服务 startservice_name: 启动指定的服务若已启动则跳过 stopservice_name: 停止正在运行的服务 setprop: 设置属性值 mkdir: 创建指定目录 symlinksym_link: 创建连接到的sym_link符号链接 write: 向文件 path 中写入字符串 exec: fork并执行会阻塞 init 进程直到程序完毕 exprot: 设置环境变量 loglevel: 设置 log 级别。 Options Options 是 Service 的可选项与 Service 配合使用 disabled: 不随 class 自动启动只根据 service 名才启动 oneshot: service 退出后不再重启 user/group: 设置执行服务的用户/用户组默认都是 root; class: 设置所属的类名当所属类启动/退出时服务也启动/停止默认为 default; onrestart: 当服务重启时执行相应命令 socket: 创建名为 /dev/socket/name 的socket critical: 在规定时间内该 service 不断重启则系统会重启并进入恢复模式。 default: 意味着 disabled false, oneshot false, critical false。 Zygote 概叙 Zygote 中文翻译为“受精卵”它主要用于孵化子进程。在 Android 系统中有以下两种程序Java 应用程序主要基于 ART(Android Runtime) 虚拟机所有的应用程序 apk 都属于这类 native 程序也就是利用 C/C 语言开发的程序如 bootanimation。所有的 Java 应用程序进程及系统服务(SystemServer)进程都由 Zygote 进程通过 Linux 的 fork() 函数卵化出来的也就是为什么把它称为 Zygote 的原因因为他就像一个受精卵卵化出无数子进程而 native 程序则由 Init 程序创建启动。Zygote 进程最初的名字不是“zygote”而是“app_process”这个名字是在 Android.mk 文件中定义的。 Zygote 是 Android 中的第一个 ART 虚拟机他通过 socket 的方式与其它进程进行通信。这里的“其他进程”其实主要是系统进程--SystemServer。 Zygote 是一个 C/S 模型Zygote 进程作为服务端它主要负责创建 Java 虚拟机加载系统资源启动 SystemServer 进程以及在后续运行过程中启动普通的应用程序其他进程作为客户端向它发出“孵化”请求而 Zygote 接收到这个请求后就“孵化”出一个新的进程。比如当点击 Launcher 里的应用程序图标去启动一个新的应用程序时这个请求会到达框架层的核心服务 ActivityManagerService 中当 AMS 收到这个请求后它通过调用 Process 类发出一个“孵化”子进程的 Socket 请求而 Zygote 监听到这个请求后就立刻 fork 一个新的进程出来。 Zygote 触发过程 1. init.zygoteXX.rc import /init.${ro.zygote}.rc ${ro.zygote} 会被替换成 ro.zygote 的属性值这个是由不同的硬件厂商自己制定的由四个值 zygote32: zygote进程对应的执行程序是 app_process纯32bit 模式 zygote64: zygote进程对应的执行程序是 app_process64纯32bit 模式 zygote32_64: 启动两个 zygote 进程(名为 zygote 和 zygote_secondary)对应的执行程序分别是 app_process32主模式、approcess63 zygote64_32: 启动两个 zygote 进程(名为 zygote 和 zygote_secondary)对应的执行程序分别是 app_process64主模式、app_precess32 2. start zygote 位置system\core\rootdir\init.rczygote-start 是在 on late-init 中触发的。 3. app_processXX 位置\frameworks\base\cmds\app_process\Zygote 启动过程 位置\frameworks\base\cmds\app_process\app_main.cpp在 app_main.cpp 的 main 函数中主要做的事情就是参数解析。这个函数有两种启动模式1. zygote 模式也就是初始化 zygote 进程传递的参数有 --start-system-server --socket - name zygote前者表示启动 SystemServer后者指定 socket 的名称。2. application模式也就是启动普通应用程序传递的参数有 class 名字以及 class 带的参数两者最终都是调用 AppRuntime 对象的 start 函数加载 ZygoteInit 或 RuntimeInit 两个 Java 类并将之前整理的参数传入进去。app_process 里面定义了三种应用程序类型 1. Zygote: com.android.internal.os.ZygoteInit 2. SystemServer 不单独启动而是由 Zygote 启动 3. 其他指定类名的 Java 程序 什么时Runtime Runtime 是支撑程序运行的基础库它是与语言绑定在一起的。比如 C Runtim: 就是 C standard lib也就是我们常说的 libc。(有意思的是Wiki 会自动将 C Runtime 重定向到C Standard Library)。 Java Runtime: 同样Wiki 将其重定向到 Java Virtual Machine这里当然包括 Java 的支撑类库(.jar)。 AndroidRuntime: 显而易见就是为 Android 应用运行所需要的运行时环境。这个环境包括以下内容 1. Dalvik VM: Android 的 Java VM, 解释运行 Dex 格式 Java 程序。每个进程运行一个虚拟机(什么叫运行虚拟机说白了就是一些 C 代码不停的去解释 Dex 格式的二进制码(Bytecode)把它们转成机器码(Machine code)然后执行当然限制大多数的 Java 虚拟机都支持 JIT也就是说bytecode 可能在运行前就以及被转换成机器码从而大大提高了性能。过去一个普遍的认识是 Java 程序比 C/C 等静态编译的语言慢但随着 JIT 的介入和发展这个有已经完全是过去式了JIT 的动态性运行允许虚拟机根据运行时环境优化机器码的生成在某些情况下Java 甚至可以比 C/C 跑得更快同时又兼具平台无关性的特性。 2. Android 的 Java 类库大部分来自于 Apache Hamony开源的 Java API 实现如 java.lang, java.util, java.net。但去除了 AWTSwing 等部件。 3. JNI: C 和 Java 互掉的接口。 4. Libc: Android 也有很多 C 代码自然少不了 libc注意的是Android 的 libc 叫 bionic C // \frameworks\base\core\jni\androidRuntime.cpp start() L1091 void AndroidRuntime::start(const char* className, const VectorString8 options, bool zygote) { ... JNIEnv* env; //JNI_CreateJavaVM L1015 if (startVm(mJavaVM, env, zygote) ! 0) { return; } onVmCreated(env); /* * Register android functions. */ if (startReg(env) 0) { ALOGE(Unable to register all android natives\n); return; } ... } Java 虚拟机的启动大致做了以下一些事情 1. 从 property 读取一系列启动参数。 2. 创建和初始化结构体全局对象每个进程GDVM及对应于 JavaVM 和 JNIEnv 的内部结构体 JavaVMExt, JNIEnvExt. 3. 初始化 java 虚拟机并创建虚拟机线程。 4. 注册系统的 JNIJava 程序通过这些 JNI 接口来访问底层的资源。 loadJniLibrary(javacore); loadJniLibrary(nativehelper); 5. 为 Zygote 的启动做最后的准备包括设置 SID/UID以及 mount 文件系统。 6. 返回 JavaVM 给 Native 代码这样它就可以向上访问 Java 的接口。 System Server 启动流程 System Server 是 Zygote fork 的第一个 java 进程这个进程非常重要因为他们有很多的系统线程提供所有核心的系统服务。 看到大名鼎鼎的 WindowManagerActivityManager 了吗对了它们都是运行在 system_server 的进程里。还有很多 Binder-x 的线程它们是各个 Service 为了响应应用程序远程调用请求而创建的。除此之外还有很多内部线程比如”UI thread, InputReader, InputDispatch 等等现在我们只关心 System Server 是如何创建起来的。 SystemServer 的 main() 函数。 public static void main(String[] args) { new SystemServer().run(); } 接下来我们分成4部分详细分析 SystemServer.run 方法的初始化流程 初始化必要的 SystemServer 环境参数比如系统时间、默认时区语言、load 一些 Library 等等。 初始化 Looper我们在主线程中使用到的 looper 就是在 SystemServer 中进行初始化的。 初始化 Context只有初始化一个 Context 才能进行启动 Service 等操作这里看一下源码 private void createSystemContext() { ActivityThread activityThread ActivityThread.systemMain(); mSystemContext activityThread.getSystemContext(); mSystemContext.setTheme(DEFAULT_SYSTEM_THEME); final Context systemUiContext activityThread.getSystemUiContext(); systemUiContext.setTheme(DEFAULT_SYSTEM_THEME); } 看到没有ActivityThread就是这个时候生成的。继续看ActivityThread中如何生成Contextpublic ContextImpl getSystemContext() {synchronized (this) {if (mSystemContext null) {mSystemContext ContextImpl.createSystemContext(this);}return mSystemContext;} }ContextImpl 是 Context 类的具体实现里面封装完成了几种常用的 createContext 的方法 static ContextImpl createSystemContext(ActivityThread mainThread) { LoadedApk packageInfo new LoadedApk(mainThread); //省略代码 return context; } static ContextImpl createSystemUiContext(ContextImpl systemContext) { final LoadedApk packageInfo systemContext.mPackageInfo; //省略代码 return context; } static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { if (packageInfo null) throw new IllegalArgumentException(packageInfo); //省略代码 return context; } static ContextImpl createActivityContext(ActivityThread mainThread, LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId, Configuration overrideConfiguration) { //省略代码 return context; } 初始化 SystemServiceManager用来管理启动 ServiceSystemServiceManager 中封装了启动 Service 的 startService 方法启动系统必要的 Service启动 service 的流程又分成三步 // Start services. try { traceBeginAndSlog(StartServices); startBootstrapServices(); startCoreServices(); startOtherServices(); SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { // } finally { traceEnd(); } 启动 BootstrapServices就是系统必须需要的服务这些服务直接耦合性很高所以就干脆放在一个方法里面一起启动比如 PowerManagerService、RecoverySystemService、DisplayMangerService、ActivityManagerService 等等启动以基本的核心 Service很简单只有三个 BatteryService、UsageStatsService、WebViewUpdateService 启动其它需要用到的 Service 比如 NetworkScoreService、AlarmManagerService Fork 函数 pid_t fork(void) 1. 参数不需要参数 2. 需要的头文件 sys/types.h 和 unistd.h 3. 返回值分两种情况 返回0表示成功创建子进程并且接下来进入子进程执行流程 返回PID0成功创建子进程并且继续执行父进程流程代码 返回非正数0创建子进程失败失败原因主要有 进程数超过系统所能创建的上限errno会被设置为EAGAIN系统内存不足errno会被设置为 ENOMEM 使用 fork() 函数得到的子进程是父进程的一个复制品它从父进程处继承了整个进程的地址空 间包括进程上下文进程执行活动全过程的静态描述、进程堆栈、打开的文件描述符、信号控 制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号计时器等只有小量信 息。因此使用 fork() 函数的代价是很大的 总结 1. init 根据 init.rc 运行 app_process并携带“-zygote 和-startSystemServer参数。 2. AndroidRuntime.cpp::start() 里将启动 JavaVM并且注册所有 framework 相关的系统 JNI 接口 3. 第一次进入 Java 世界运行 ZygoteInit.java::main() 函数初始化 Zygote并创建 Socket 的 Server 端。 4. 然后 fork 一个新的进程并在新进程里初始化 SystemServer.Fork 之前Zygote 是 preload 常用的 Java 类库以及系统的 resource同时 GC 清理内存空间为子进程省去重复的工作。 5. SystemServer 将所有的系统 Service 初始化包括 ActivityManager 和 WindowManager他们是应用程序运行起来的前提。 6. 依次同时Zygote 监听服务端 Socket等待新的应用启动请求。 7. ActivityManager ready 之后寻找系统的 “Startup Application将请求发给 Zygote。 8. Zygote 收到请求后fork 出一个新的进程。 9. Zygote 监听并处理 SystemServer 的 SIGCHID 信号一旦 SystemServer 崩溃立即将自己 kill 掉。init 会重启 Zygote。 面试题 1. 你了解 Android 系统启动流程吗 答当按电源键触发开机首先会从 ROM 中预定义的地方加载引导程序 BootLoader 到 RAM 中并执 行 BootLoader 程序启动 Linux Kernel 然后启动用户级别的第一个进程 init 进程。init 进程会解析 init.rc 脚本做一些初始化工作包括挂载文件系统、创建工作目录以及启动系统服务进程等其中系统 服务进程包括 Zygote、service manager、media 等。在 Zygote 中会进一步去启动 system_server 进 程然后在 system_server 进程中会启动 AMS、WMS、PMS 等服务等这些服务启动之后AMS 中就 会打开 Launcher 应用的 home Activity最终就看到了手机的 桌面。 2. system_server 为什么要在 Zygote 中启动而不是由 init 直接启动呢 答Zygote 作为一个孵化器可以提前加载一些资源这样 fork() 时基于 Copy-On-Write 机制创建的其 他进程就能直接使用这些资源而不用重新加载。比如 system_server 就可以直接使用 Zygote 中的 JNI 函数、共享库、常用的类、以及主题资源。 3. 为什么要专门使用 Zygote 进程去孵化应用进程而不是让 system_server 去孵化呢 答首先 system_server 相比 Zygote 多运行了 AMS、WMS 等服务这些对一个应用程序来说是不需要 的。另外进程的 fork() 对多线程不友好仅会将发起调用的线程拷贝到子进程这可能会导致死锁而 system_server 中肯定是有很多线程的。 4. 能说说具体是怎么导致死锁的吗 答在 POSIX 标准中fork 的行为是这样的复制整个用户空间的数据通常使用 copy-on-write 的策略 所以可以实现的速度很快以及所有系统对象然后仅复制当前线程到子进程。这里所有父进程中别 的线程到了子进程中都是突然蒸发掉的对于锁来说从 OS 看每个锁有一个所有者即最后一次 lock 它的线程。假设这么一个环境在 fork 之前有一个子线程 lock 了某个锁获得了对锁的所有权。fork 以后在子进程中所有的额外线程都 人间蒸发了。而锁却被正常复制了在子进程看来这个锁没有主人所以没有任何人可以对它解锁。 当子进程想 lock 这个锁时不再有任何手段可以解开了。程序发生死锁 5. Zygote 为什么不采用 Binder 机制进行 IPC 通信 答Binder 机制中存在 Binder 线程池是多线程的如果 Zygote 采用 Binder 的话就存在上面说的 fork() 与 多线程的问题了。其实严格来说Binder 机制不一定要多线程所谓的 Binder 线程只不过是 在循环读取 Binder 驱动的消息而已只注册一个 Binder 线程也是可以工作的比如 service manager 就是这样的。实际上 Zygote 尽管没有采取 Binder 机制它也不是单线程的但它在 fork() 前主动停止 了其他线程fork() 后重新启动了。
http://www.tj-hxxt.cn/news/230357.html

相关文章:

  • 深圳做微藻的公司网站网站 内容 营销
  • 有网站做点什么好.net 网站模板下载地址
  • 公司建一个网站要多少钱网络架构规划
  • 网站开发的分工seo网络优化招聘信息
  • 给前端做网站的图片叫什么软件调查问卷 wordpress
  • 实业公司网站建设使用的电脑做网站的服务器
  • 常州好的网站设计公司凡科互动平台
  • 淘宝网站的建设企业网站建设费用摊销
  • 苏州知名网站建设推广策略英语
  • 单页网站赚钱友情链接的形式有哪些
  • 做网站 当站长北京网站设计建设
  • 兰州建设网站的公司优质网站建设服务
  • 南京建设机械网站衡水注册公司流程和费用
  • 计算机程序设计网站开发有哪些做搞笑视频的网站
  • 搜索关键字搜索到网站杭州seo博客
  • linode wordpress建站官方进一步优化
  • 网站建设策划文案广州网站下载安装
  • 网站建设补贴网站建设中 html5
  • 大连网站建设价格低wordpress返回顶部图标
  • 网站活动页面做业务网站
  • 建设个网站需要什么wordpress lnmp1.4
  • 和网站建设签合同小程序运营推广公司
  • 网站品牌推广设计专门做民宿的网站
  • 凡科建站app只有一个页面的网站
  • 安防监控网站模板常州网站建设价位
  • 零基础学习做网站多商户商城源码下载
  • 网站logo模板go语言 网站开发
  • 斐讯k2做网站彩票网站开发制作h5
  • 建设银行锦州分行网站wordpress怎么看访问量
  • 网站app用什么语言开发中国核工业二四建设有限公司