android开机过程.doc_第1页
android开机过程.doc_第2页
android开机过程.doc_第3页
android开机过程.doc_第4页
android开机过程.doc_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一、 Android开机启动流程简介1、 OS-level:由bootloader载入linux kernel后kernel开始初始化, 并载入built-in的驱动程序。Kernel完成开机后,载入init process,切换至user-space。 Init进程是第一个在user-space启动的进程。2、 Android-level:由init process读取init.rc,Native 服务启动,并启动重要的外部程序,例如:servicemanager、Zygote以及System Server等。由 init process 根据硬件类型读取init.xxx.rc。由init.xxx.rc加载init.xxx.sh。由 init.xxx.sh 加载特定的硬件驱动。如hi_tuner.ko、hi_demux.ko等。3、 Zygote-Mode:Zygote 启动完SystemServer 后,进入Zygote Mode,在Socket 等候命令。随后,使用者将看到一个桌面环境(Home Screen)。桌面环境由一个名为Launcher的应用程序负责提供。本文档重点研究Android-level中的启动流程。启动流程如下图所示:二、 init process流程分析init进程简介init进程是第一个在user-space启动的进程。由内核启动参数init传递给内核,如果该项没有设置,内核会按/etc/init,/bin/init,/sbin/init,/bin/sh的顺序进行尝试,如果都有的都没找到,内核会抛出 kernel panic:的错误。init进程包含在跟文件系统中,跟文件系统被直接编译到了内核。对init进程的修改,需要重新编译烧写内核。编译命令:#cd kernel#make uImagCONFIG_INITRAMFS_SOURCE=./out/target/product/Hi3716C/root/ -j 8#cp kernel/arch/arm/boot/uImage out/target/product/Hi3716C/kernel -afv源代码路径:froyosystemcoreinit编译的文件:builtins.cinit.cdevices.cproperty_service.cutil.c parser.clogo.c编译命令: make init生成的文件:/out/target/product/Hi3716C/root/initinit进程启动流程1. 安装SIGCHLD信号。sigaction(SIGCHLD, &act, 0);如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。因此需要对SIGCHLD信号做出处理,回收僵尸进程的资源,避免造成不必要的资源浪费。2. 对umask进行清零。umask(0);umask是什么?登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情。umask设置了用户创建文件的默认权限,它与chmod的效果刚好相反,umask设置的是权限“补码”,而chmod设置的是文件权限码。设置文件的默认权限,umask和chmod的权限刚好反的,umask的0000相当于chmod的0777。3. 为rootfs建立必要的文件夹,并挂载适当的分区。mkdir(/dev, 0755);mkdir(/proc, 0755);mkdir(/sys, 0755);mount(tmpfs, /dev, tmpfs, 0, mode=0755);mkdir(/dev/pts, 0755);mkdir(/dev/socket, 0755);mount(devpts, /dev/pts, devpts, 0, NULL);mount(proc, /proc, proc, 0, NULL);mount(sysfs, /sys, sysfs, 0, NULL);4. 创建/dev/null和/dev/kmsg节点。创建/dev/null结点,重定向标准输入,输出以及标准出错。open_devnull_stdio();创建/dev/kmsg设备结点,我们可以利用这个设备输出调试信息log_init();5. 解析/init.rc,将所有服务和操作信息加入链表。解析初始化脚本,这里只是parse,将脚本解析到一个链表中,并没有执行。parse_config_file(/init.rc); 6. 从/proc/cmdline中提取信息内核启动参数,并保存到全局变量。qemu_init(); import_kernel_cmdline(0);7. 根据6获得的hardware参数信息,解析额外的硬件相关init脚本.hi3726c 中为 init.godbox.rc get_hardware_name(); snprintf(tmp, sizeof(tmp), /init.%s.rc, hardware); parse_config_file(tmp); 8. 找到init.rc paser链表中为early-init属性的项目,将其添加到action queue中,并执行执行这些queue中的动作。action_for_each_trigger(early-init, action_add_queue_tail); drain_action_queue();9. 遍历/sys文件夹,是内核产生设备添加事件(为了自动产生设备节点)。device_fd = device_init();10. 初始化属性系统,并导入初始化属性文件。property_init();每个属性都有一个名称和值,它们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。在系统初始化时,Android将分配一个共享内存区来存储的属性,这里主要是从/p属性文件读取属性。类似于像Windows下的注册表的作用。/的内容ro.secure=0ro.allow.mock.location=1ro.debuggable=1persist.service.adb.enable=111. 从属性系统中得到ro.debuggable,若为1,則初始化keychord监听。keychord_fd = open_keychord();12. 判断是否有控制台,如果没有,就尝试是否是可以打缺省的控制台。缺省控制台名称:static char *console_name = /dev/console;if (console0) snprintf(tmp, sizeof(tmp), /dev/%s, console);console_name = strdup(tmp);fd = open(console_name, O_RDWR);if (fd = 0)have_console = 1;close(fd);13. 读取/initlogo.rle,如果成功則在/dev/graphics/fb0显示Logo,如果失败则将/dev/tty0设为文本模式,并打开/dev/tty0,输出文本“ANDROID”。if( load_565rle_image(INIT_IMAGE_FILE) ) fd = open(/dev/tty0, O_WRONLY);if (fd = 0) const char *msg;msg = nnnnnnn /*console is 40 cols x 30 lines*/nnnnnnn A N D R O I D ;write(fd, msg, strlen(msg);close(fd);14. 判断是否使用模拟器运行,如果时,就加载内核命令行参数。if (qemu0)import_kernel_cmdline(1);15. 根据内核命令行参数来设置工厂模式测试。if (!strcmp(bootmode,factory)property_set(ro.factorytest, 1);else if (!strcmp(bootmode,factory2)property_set(ro.factorytest, 2);elseproperty_set(ro.factorytest, 0);16. 设置序列号属性值。property_set(ro.serialno, serialno0 ? serialno : );17. 设置启动模式属性值。property_set(ro.bootmode, bootmode0 ? bootmode : unknown);18. 设置基带频率属性值。property_set(ro.baseband, baseband0 ? baseband : unknown);19. 设置硬件载波方式属性值。property_set(ro.carrier, carrier0 ? carrier : unknown);20. 设置引导程序的版本号属性值。property_set(ro.bootloader,bootloader0?bootloader: unknown);21. 设置硬件信息属性值。property_set(ro.hardware, hardware);22. 设置硬件版本号属性值snprintf(tmp, PROP_VALUE_MAX, %d, revision);property_set(ro.revision, tmp);23. 添加所有的init命令到队列,然后再执行。action_for_each_trigger(init, action_add_queue_tail);drain_action_queue();24. 加载system和data目录下的属性,并启动属性监听服务。property_set_fd = start_property_service();加载的属性文件为:#define PROP_PATH_SYSTEM_BUILD /system/p#define PROP_PATH_SYSTEM_DEFAULT /system/p#define PROP_PATH_LOCAL_OVERRIDE /data/p25. 创建一个全双工的通讯机制的两个SOCKET,信号可以在signal_fd和signal_recv_fd双向通讯,从而建立起沟通的管道。这个信号管理,就是用来让init进程与它的子进程进行沟通的,子进程从signal_fd写入信息,init进程从signal_recv_fd收到信息,然后再做处理。if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) = 0) signal_fd = s0;signal_recv_fd = s1;fcntl(s0, F_SETFD, FD_CLOEXEC);fcntl(s0, F_SETFL, O_NONBLOCK);fcntl(s1, F_SETFD, FD_CLOEXEC);fcntl(s1, F_SETFL, O_NONBLOCK);26. 判断设备文件系统device_fd是否成功初始化,属性服务property_set_fd是否成功初始化,信号通讯机制signal_recv_fd是否成功初始化。if (device_fd 0)|(property_set_fd 0)|(signal_recv_fd 0) ufds3.fd = keychord_fd;ufds3.events = POLLIN;fd_count+; else ufds3.events = 0;ufds3.revents = 0;31. 初始化linux程序启动速度的性能分析工具。#if BOOTCHARTbootchart_count = bootchart_init();if (bootchart_count 0) NOTICE(bootcharting started (period=%d ms)n,bootchart_count*BOOTCHART_POLLING_MS); else NOTICE(bootcharting ignoredn);#endif32. 进入主进程循环,重置轮询事件状态、查询action队列,并执行、重启需要重启的服务、轮询注册的事件状态。for(;) int nr, i, timeout = -1;for (i = 0; i fd_count; i+)ufdsi.revents = 0;drain_action_queue();restart_processes();if (process_needs_restart) timeout = (process_needs_restart - gettime() * 1000;if (timeout 0) if (timeout BOOTCHART_POLLING_MS)timeout = BOOTCHART_POLLING_MS;if (bootchart_step() 0 | -bootchart_count = 0) bootchart_finish();bootchart_count = 0;#endifnr = poll(ufds, fd_count, timeout);if (nr = 0)continue;if (ufds2.revents = POLLIN) /* we got a SIGCHLD - reap and restart as needed */read(signal_recv_fd, tmp, sizeof(tmp);while (!wait_for_one_process(0);continue;if (ufds0.revents = POLLIN)handle_device_fd(device_fd);if (ufds1.revents = POLLIN)handle_property_set_fd(property_set_fd);if (ufds3.revents = POLLIN)handle_keychord(keychord_fd);三、 init.rc 脚本加载流程分析1、init.rc 脚本语法介绍Android初始化语言由四大类声明组成:行为类(Actions),命令类(Commands),服务类(Services),选项类(Options)。* 初始化语言以行为单位,由以空格间隔的语言符号组成。C风格的反斜杠转义符可以用来插入空白到语言符号。双引号也可以用来防止文本被空格分成多个语言符号。当反斜杠在行末时,作为折行符。* 以#开始(前面允许有空格)的行为注释行。* Actions和Services隐含声明一个新的段落。所有该段落下Commands或Options的声明属于该段落。第一段落前的Commands或Options被忽略。* Actions和Services拥有独一无二的命名。在它们之后声明相同命名的类将被当作错误并忽略。l ActionsActions是一系列命令的命名。Actions拥有一个触发器(trigger)用来决定action何时执行。当一个action在符合触发条件被执行时,如果它还没被加入到待执行队列中的话,则加入到队列最后。队列中的action依次执行,action中的命令也依次执行。Init在执行命令的中间处理其它活动(设备创建/销毁,property设置,进程重启)。Actions语法形式为:on .l Services Services是由init启动,在它们退出时重启(可选)。Service表现形式为:service * .l OptionsOptions是Services的修饰,它们影响init何时、如何运行service.critical这是一个设备关键服务(device-critical service) .如果它在4分钟内退出超过4次,设备将重启并进入恢复模式。disabled该服务将不会自动启动,它必须被依照服务名指定启动才可以启动。setenv 设置已启动的进程的环境变量的值socket 创建一个名为/dev/socket/的unix domin socket,并传送它的fd到已启动的进程。必须为dgram或stream.用户和组默认为0.user 在执行服务前改变用户名。group *在执行服务前改变组。在第一个组后的组将设为进程附加组(通过setgroups().当前默认为root.oneshot在服务退出后不重启。class 为service指定一个类别名。同样类名的所有的服务可以一起启动或停止。如果没有指定类别的服务默认为default类。onrestart当服务重启时执行一个命令。l Triggers触发器是一个字符串,可以用来匹配某种类型的事件并执行一个action。Boot这是当init开始后执行的第一个触发器(当/init.conf被加载)=当property 被设为指定的值时触发。device-added-device-removed-当设备节点被添加或移除时触发。service-exited-当指定的服务存在时触发l Commandsexec *Fork并执行一个程序().这将被block直到程序执行完毕。最好避免执行例如内建命令以外的程序,它可能会导致init被阻塞不动。export 设定全局环境变量的值,当这个命令执行后所有的进程都可以取得该环境变量的值。ifup 使网络接口联机。import 解析一个init配置文件,扩展当前配置文件。hostname 设置主机名chmod 改变文件访问权限chown 改变文件所属和组class_start 当指定类别的服务没有运行,启动该类别所有的服务。class_stop 当指定类别的服务正在运行,停止该类别所有的服务。domainname 设置域名。insmod 加载该路径的模块mkdir mode owner group在创建一个目录,可选选项:mod,owner,group.如果没有指定,目录以755权限,owner为root,group为root创建。mount *尝试mount 到目录. 可以用mtdname格式以命名指定一个mtd块设备。包含ro,rw,remount,noatime.setprop 设置系统property 的值.setrlimit 设置resource的rlimit.start 启动一个没有运行的服务。stop 停止一个正在运行的服务。symlink 创建一个的符号链接到sysclktz 设置系统时区(GMT为0)trigger 触发一个事件。用于调用其它action。write *打开的文件并写入一个或多个字符串。l PropertiesInit会更新一些系统property以提供查看它当前的状态。init.action当前正在执行的action,如果没有则为mand被执行的命令,如果没有则为init.svc.命名为的服务的状态(stopped, running, restarting)2、init.rc 脚本启动的服务介绍l service console /system/bin/shconsolesh服务的代码在目录:froyo/system/core/shsh服务是控制台服务,是从NetBSD移植过来的,它的命令也是比较有限。sh服务使用flex工具生成词法分析代码,使用bison生成语法分析代码。l service adbd /sbin/adbddisabledadbd服务的代码在目录:froyo/system/core/adbadbd服务是adb调试系统中的一部分,整个adb调试系统包括有三部分:手机运行的adbd服务PC运行的服务器PC运行的客户端当android启动时,就运行adbd服务,创建一个调试端口,这样就可以让开发机器上的服务器连接过来,通过这个连接就可以发送调试信息给服务器,也可以接收到外面发送过来的调试命令。adbd依据下面的条件启动或停止。on property:ro.kernel.qemu=1 start adbdon property:persist.service.adb.enable=1 start adbdon property:persist.service.adb.enable=0 stop adbdl service servicemanager /system/bin/servicemanageruser systemcriticalonrestart restart zygoteonrestart restart mediaservicemanager服务的代码在目录:froyo/frameworks/base/cmds/servicemanagerservicemanager服务的作用主要是服务管理。所谓的服务管理其实就是获取服务、检查服务、添加服务、枚举所有服务。服务管理器是一个容器管理器,方便服务添加、调用和删除。在应用层的程序,都向这个服务管理器获取需要使用的服务,而所有提供服务的程序,都向这个服务器管理器注册自己的服务。服务管理器是应用程序与服务沟通的桥梁。l service vold /system/bin/voldsocket vold stream 0660 root mountioprio be 2vold服务的代码在目录:froyo/system/core/voldvold服务的作用主要是负责完成系统的动态卷管理,比如cdrom、u盘、mmc卡等外存储的管理。当有这外存储设备插入时,就需要监视这种变化,并加载相应的驱动程序,然后报告给系统和应用程序有新存储设备可以使用。vold处理过程大致分为三步:1)创建链接:在vold作为一个守护进程,一方面接受驱动的信息,并把信息传给应用层;另一方面接受上层的命令并完成相应。所以这里的链接一共有两条:A. vold socket: 负责vold与应用层的信息传递;B. 访问udev的socket: 负责vold与底层的信息传递;这两个链接都是在进程的一开始完成创建的。2)引导:这里主要是在vold启动时,对现有外设存储设备的处理。首先,要加载并解析vold.conf,并检查挂载点是否已经被挂载;其次,执行MMC卡挂载;最后,处理USB大容量存储。3)事件处理:这里通过对两个链接的监听,完成对动态事件的处理,以及对上层应用操作的响应。l service debuggerd /system/bin/debuggerdl service zygote /system/bin/app_process -Xzygote /system/bin -zygote -start-system-serversocket zygote stream 666onrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediazygote服务的代码在目录:froyo/frameworks/base/cmds/app_processzygote服务主要作用就是创建一个服务监听用户的命令,并且根据用户的命令创建应用程序运行。所有的java应用程序进程都是由zygote派生出来的。是虚拟机实例的孵化器。l service media /system/bin/mediaserveruser mediagroup system audio camera graphics inet net_bt net_bt_adminioprio rt 4mediaserver服务的代码在目录:froyo/frameworks/base/media/mediaservermediaserver服务是多媒体服务的守护进程,负责多媒体照相机音频等三项服务。l service bootanim /system/bin/bootanimationuser graphicsgroup graphicsdisabledoneshotbootanimation 服务的代码在目录:froyo/frameworks/base/cmds/bootanimationbootanimation 服务是开机动画,主要用来加载动画资源。l service dbus /system/bin/dbus-daemon -system -noforksocket dbus stream 660 bluetooth bluetoothuser bluetoothgroup bluetooth net_bt_admindbus服务的代码在目录:froyo/external/dbus/busdbus服务是android使用的一种特殊的进程间通讯系统。它具有面向对象接口的协议,以及应用程序之间互相发现和监视的守护进程。dbus设计用来作为用户与系统服务之间的分隔以及系统服务之间的通讯。因此,dbus通讯安全,但效率有点差。l service bluetoothd /system/bin/bluetoothd -nsocket bluetooth stream 660 bluetooth bluetoothsocket dbus_bluetooth stream 660 bluetooth bluetoothgroup bluetooth net_bt_admin miscdisabledbluetoothd服务的代码在目录:froyo/external/bluetooth/bluez/srcl service hfag /system/bin/sdptool add -channel=10 HFAGuser bluetoothgroup bluetooth net_bt_admindisabledoneshotHFAG(handsfreeaudiogateway)蓝牙免提服务。hfag服务的代码在目录:froyo/external/bluetooth/bluez/toolsl service hsag /system/bin/sdptool add -channel=11 HSAGuser bluetoothgroup bluetooth net_bt_admindisabledoneshotHSAG(headsetaudiogateway)可能跟蓝牙耳机服务。hsag服务的代码在目录:froyo/external/bluetooth/bluez/toolsl service opush /system/bin/sdptool add -channel=12 OPUSHuser bluetoothgroup bluetooth net_bt_admindisabledoneshotOPUSH(ObjectPush)就是OPP服务,通过这个服务可以推送对象到另一个有这个服务的设备中。opush服务的代码在目录:froyo/external/bluetooth/bluez/toolsl service pbap /system/bin/sdptool add -channel=19 PBAPuser bluetoothgroup bluetooth net_bt_admindisabledoneshotPBAP(PhoneBookAccess)提供通过蓝牙传送手机电话本的一个服务协议。pbap服务的代码在目录:froyo/external/bluetooth/bluez/toolsl service hciattach /system/bin/hciattach -n /dev/ttyAMA0 -s 115200user bluetoothgroup bluetooth net_bt_admindisabledoneshothciattach服务的代码在目录:froyo/external/bluetooth/bluez/toolshciattach服务主要用来初始化蓝牙设备。l service installd /system/bin/installdsocket installd stream 600 system systeminstalld 服务的代码在目录:froyo/frameworks/base/cmds/installdinstalld服务是提供安装dex文件的服务。dex是Dalvik VM executes的全称,即Android Dalvik执行程序,并非Java ME的字节码而是Dalvik字节码。l service flash_recovery /system/etc/install-recovery.shoneshot刷机用的一个服务,这个可以去掉。我们的代码包里没有install-recovery.sh这个文件。l service racoon /system/bin/racoonsocket racoon stream 600 system system group net_admindisabledoneshotracoon服务的代码在目录:froyo/external/ipsec-toolsIPsectools包括setkey(配置规则策略)和racoon(密钥协商)。Setkey实现IPSec中SPD管理和SAD的管理,Racoon是IPSec-tools中IKE的实现。racoon支持多种验证方式,包括预共享密钥和X.509证书方式。l service mtpd /system/bin/mtpdsocket mtpd stream 600 system systemuser vpngroup vpn net_admin net_rawdisabledoneshotmtpd服务的代码在目录:froyo/external/mtpdmtpd支持VPN的服务,支持PPTP和L2TP两种协议。l service keystore /system/bin/keystore /data/misc/keystoreuser keystoregroup keystoresocket keystore stream 666keystore服务的代码在目录:froyo/frameworks/base/cmds/keystorekeystore服务是加解密储存键值的服务。它主要作用就是验证应用程序与签名文件是否一致。l service dumpstate /system/bin/dumpstate -ssocket dumpstate stream 0660 shell logdisabledoneshotdumpstate服务的代码在目录:froyo/frameworks/base/cmds/dumpstate/dumpstate服务是用来打印系统信息。如编译时间、Bootloader版本、MEMORY INFO、CPU INFO等信息。四、 init.xxx.rc 脚本加载流程分析1、init.xxx.rc的由来init.xxx.rc由init进程负责加载,相关代码如下:get_hardware_name();实际就是取/proc/cpuinfo中Hardware字段。# cat /proc/cpuinfoProcessor : ARMv7 Processor rev 2 (v7l)BogoMIPS : 1005.97Features : swp half thumb fastmult vfp edsp vfpv3 vfpv3d16 CPU implementer : 0x41CPU architecture: 7CPU variant : 0x2CPU part : 0xc09CPU revision : 2Hardware : godboxRevision : 0000Serial : 0000000000000000snprintf(tmp, sizeof(tmp), /init.%s.rc, hardware);这里tmp的值就等于 /init.godbox.rcparse_config_file(tmp);因此在HI3716C平台第二加载的脚本就是/init.godbox.rc2、init.godbox.rc脚本内容分析设置环境变量on init export PATH /sbin:/system/sbin:/system/bin:/system/xbin:/system/busybox/bin:/system/busybox/sbin设置一些属性值。on boot setprop ARGH ARGH setprop status.battery.state Slow setprop status.battery.level 5 setprop status.battery.level_raw 50 setprop status.battery.level_scale 9加载/system/etc/init.godbox.sh脚本service hix5hd-setup /system/etc/init.godbox.sh oneshot启动logcat服务service hix5hd-logcat /system/bin/logcat -Q oneshotlogcat服务的代码在目录:froyo/system/core/logcat/五、 init.xxx.sh 脚本加载流程分析1、 init.xxx.sh的由来由init.godbox.rc脚本加载,加载命令如下:service hix5hd-setup /system/etc/init.godbox.sh oneshot2、init.godbox.sh 脚本内容分析#!/system/bin/sh#关闭stagefright多媒体引擎setprop media.stagefright.enable-player falsesetprop media.stagefright.enable-meta falsesetprop media.stagefright.enable-scan falsesetprop media.stagefright.enable-http false#关闭jni参数检查setprop dalvik.vm.checkjni false# setprop for disp_channel 设置显示通道为1setprop ro.sf.display_channel 1 insmod /system/lib/modules/hi_media.ko#DDR 1GB 内存mmz加载方式#bootargs mem=808M vmalloc=600M/system/busybox/sbin/insmod /system/lib/modules/hi_mmz.ko mmz=vdec,0,0xb3200000,57M:JPEG,0,0xb6b00000,23M:ddr,0,0xb8200000,30M#DDR 512M 内存mmz加载方式#bootargs mem=306M vmalloc=600M#/system/busybox/sbin/insmod /system/lib/modules/hi_mmz.ko mmz=vdec,0,0x93200000,57M:JPEG,0,0x96b00000,23M:ddr,0,0x98200000,30M# for system standby 加载系统待机驱动

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论