- 浏览: 117567 次
- 性别:
- 来自: 广州
最新评论
-
沉沦书生:
...
Android APK程序开发最简单入门文档andbook -
chen-kaka:
谢谢分享!
书籍推荐:搜索引擎技术入门书籍 -
ainiziling:
哇哈哈!!
书籍推荐:搜索引擎技术入门书籍 -
至尊宝_唯一:
这本书的确是好书,也谢谢LZ
书籍推荐:搜索引擎技术入门书籍 -
xixian:
谢谢分享~~~
书籍推荐:搜索引擎技术入门书籍
Android 系统启动分析(转)
init进程是Android启动后系统执行的第一个名称为init的可执行程序。这个程序以一个守护进程的方式运行,它提供了以下功能:
1、init可执行程序
init 可执行文件是系统运行的第一个用户空间程序,它以守护进程的方式运行。因此这个程序的init.c文件包含main函数的入口,基本分析如下:int main(int argc, char **argv) { (省略若干。。。) umask(0); /*对umask进行清零。*/ mkdir("/dev", 0755);/*为rootfs建立必要的文件夹,并挂载适当的分区。 */ 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); /*创建/dev/null和/dev/kmsg节点*/ open_devnull_stdio(); log_init(); /*解析/init.rc,将所有服务和操作信息加入链表。*/ INFO("reading config file\n"); parse_config_file("/init.rc"); /*获取内核命令行参数*/ qemu_init(); import_kernel_cmdline(0); /*先从上一步获得的全局变量中获取信息硬件信息和版本号,如果没有则从/proc/cpuinfo中提取, *并保存到全局变量。根据硬件信息选择一个/init.(硬件).rc,并解析,将服务和操作信息加入链表。 */ get_hardware_name(); snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); parse_config_file(tmp); /*执行链表中带有“early-init”触发的的命令。*/ action_for_each_trigger("early-init", action_add_queue_tail); drain_action_queue(); /*遍历/sys文件夹,是内核产生设备添加事件(为了自动产生设备节点)。 *初始化属性系统,并导入初始化属性文件。用于在系统运行过程中动态创建设备节点、删除设备节点等操作 */ INFO("device init\n"); device_fd = device_init(); property_init(); // 从属性系统中得到ro.debuggable,若为1,则初始化keychord监听。 debuggable = property_get("ro.debuggable"); if (debuggable && !strcmp(debuggable, "1")) { keychord_fd = open_keychord(); } /*打开console,如果cmdline中没有指定的console则打开默认的/dev/console*/ if (console[0]) { 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); /*读取/initlogo.rle(一张位图),如果成功则在/dev/graphics/fb0 显示Logo,如果失败则将/dev/tty0 *设为TEXT模式并打开/dev/tty0,输出文本ANDROID(本人修改为Zhao Rui Jia做为启动项目的修改)。 */ if( load_565rle_image(INIT_IMAGE_FILE) ) { fd = open("/dev/tty0", O_WRONLY); if (fd >= 0) { const char *msg; msg = "\n" "\n" "\n" "\n" "\n" "\n" "\n" // console is 40 cols x 30 lines "\n" "\n" "\n" "\n" "\n" "\n" "\n" /*" A N D R O I D ";*/ " z h a o R u i J i a"; write(fd, msg, strlen(msg)); close(fd); } } /* 判断cmdline 中的參數,并设置属性系统中的参数: * 1、 如果 bootmode为 * - factory,设置ro.factorytest值为1 * - factory2,设置ro.factorytest值为2 * - 其他的設ro.factorytest值為0 * 2、如果有serialno参数,则设置ro.serialno,否则为"" * 3、如果有bootmod参数,则设置ro.bootmod,否则为"unknown" * 4、如果有baseband参数,则设置ro.baseband,否则为"unknown" * 5、如果有carrier参数,则设置ro.carrier,否则为"unknown" * 6、如果有bootloader参数,则设置ro.bootloader,否则为"unknown" * 7、通过全局变量(前面从/proc/cpuinfo中提取的)设置ro.hardware和ro.version。 */ if (qemu[0]) import_kernel_cmdline(1); if (!strcmp(bootmode,"factory")) property_set("ro.factorytest", "1"); else if (!strcmp(bootmode,"factory2")) property_set("ro.factorytest", "2"); else property_set("ro.factorytest", "0"); property_set("ro.serialno", serialno[0] ? serialno : ""); property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown"); property_set("ro.baseband", baseband[0] ? baseband : "unknown"); property_set("ro.carrier", carrier[0] ? carrier : "unknown"); property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown"); property_set("ro.hardware", hardware); snprintf(tmp, PROP_VALUE_MAX, "%d", revision); property_set("ro.revision", tmp); /*执行所有触发标识为init的action。*/ action_for_each_trigger("init", action_add_queue_tail); drain_action_queue(); property_set_fd = start_property_service(); /* 为sigchld handler创建信号机制*/ if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) { signal_fd = s[0]; signal_recv_fd = s[1]; fcntl(s[0], F_SETFD, FD_CLOEXEC); fcntl(s[0], F_SETFL, O_NONBLOCK); fcntl(s[1], F_SETFD, FD_CLOEXEC); fcntl(s[1], F_SETFL, O_NONBLOCK); } /* 确认所有初始化工作完成 * device_fd(device init 完成) * property_set_fd(property server start 完成) * signal_recv_fd (信号机制建立) */ if ((device_fd < 0) || (property_set_fd < 0) || (signal_recv_fd < 0)) { ERROR("init startup failure\n"); return 1; } /* execute all the boot actions to get us started */ action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); drain_action_queue(); /* run all property triggers based on current state of the properties */ queue_all_property_triggers(); drain_action_queue(); /* enable property triggers */ property_triggers_enabled = 1; /* * 注册轮询事件: * - device_fd * - property_set_fd * -signal_recv_fd * -如果有keychord,则注册keychord_fd */ ufds[0].fd = device_fd; ufds[0].events = POLLIN; ufds[1].fd = property_set_fd; ufds[1].events = POLLIN; ufds[2].fd = signal_recv_fd; ufds[2].events = POLLIN; fd_count = 3; if (keychord_fd > 0) { ufds[3].fd = keychord_fd; ufds[3].events = POLLIN; fd_count++; } else { ufds[3].events = 0; ufds[3].revents = 0; } /*如果支持BOOTCHART,则初始化BOOTCHART*/ #if BOOTCHART bootchart_count = bootchart_init(); if (bootchart_count < 0) { ERROR("bootcharting init failure\n"); } else if (bootchart_count > 0) { NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS); } else { NOTICE("bootcharting ignored\n"); } #endif /* *进入主进程循环: * - 重置轮询事件的接受状态,revents为0 * - 查询action队列并执行。 * - 重启需要重启的服务 * - 轮询注册的事件 * - 如果signal_recv_fd的revents为POLLIN,则得到一个信号,获取并处理 * - 如果device_fd的revents为POLLIN,调用handle_device_fd * - 如果property_fd的revents为POLLIN,调用handle_property_set_fd * - 如果keychord_fd的revents为POLLIN,调用handle_keychord */ for(;;) { int nr, i, timeout = -1; for (i = 0; i < fd_count; i++) ufds[i].revents = 0; drain_action_queue(); restart_processes(); if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } #if BOOTCHART if (bootchart_count > 0) { if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) timeout = BOOTCHART_POLLING_MS; if (bootchart_step() < 0 || --bootchart_count == 0) { bootchart_finish(); bootchart_count = 0; } } #endif nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; if (ufds[2].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 (ufds[0].revents == POLLIN) handle_device_fd(device_fd); if (ufds[1].revents == POLLIN) handle_property_set_fd(property_set_fd); if (ufds[3].revents == POLLIN) handle_keychord(keychord_fd); } return 0; }
2、启动脚本init.rc
mkdir /sdcard 0000 system system mkdir /system mkdir /data 0771 system system mkdir /cache 0770 system cache mkdir /config 0500 root root mkdir /sqlite_stmt_journals 01777 root root mount tmpfs tmpfs /sqlite_stmt_journals size=4m
这些命令在init可执行程序中被解析,然后调用相关的函数来实现。 Actions(动作)表示一系列的命令,通常在Triggers(触发条件)中调用,动作和触发条件例如:
on init export PATH /sbin:/system/sbin:/system/bin:/system/xbin
service vold /system/bin/vold socket vold stream 0660 root mount service bootsound /system/bin/playmp3 user media group audio oneshot
setprop ro.FOREGROUND_APP_MEM 1536 setprop ro.VISIBLE_APP_MEM 2048 start adbd
setprop 用于设置属性,on property可以用于判断属性,这里的属性在整个Android系统运行中都是一致的。
综上如果想要修改启动过程只需要修改init.c或者init.rc里的内容即可.
参考资料
发表评论
-
android调用隐藏的网络信息设置菜单实现
2010-09-15 20:57 3622Android 调用 内置的 ... -
Android开机自启动程序设置及控制方法思路浅谈
2010-09-12 16:31 5999Android系统通过应用程序自行在系统中登记注册事件(即In ... -
Android刷机原理之recovery内部工作原理
2010-09-09 20:01 3545现在Android版本更新太快,2.1是最普遍的版本,不过马上 ... -
Android运行底层linux外部命令的实现
2010-09-03 10:58 8666Android运行底层linux外部命令的实现 a ... -
Android开发傻瓜入门-开发自己的手机短信发送程序
2010-08-29 00:49 2283Android傻瓜开发实例-手机短信发送程序 一、用E ... -
Android UI 用户界面开发基本概念概览
2010-08-28 20:52 2897Android UI界面编程概览 本文主要对Andro ... -
Android signed APK程序正式签名方法详解
2010-08-28 18:55 8408Android程序的签名用户在开发时通过ADB接口上传的程序会 ... -
Android开机自动启动程序设置
2010-08-08 22:59 8167Android开机自启动 1.定义一个Broadc ... -
Android 2.1 源码目录结构分析 (转)
2010-08-03 21:20 2459Android 2.1 源码目录结构 ... -
Milestone解决耳机拔掉后音乐继续响的办法
2010-08-03 19:58 1443【monner题记】最近Android真是炙手可热啊,值得研究 ...
相关推荐
在内容上,《Android系统源代码情景分析(含CD光盘1张)》结合使用情景,全面、深入、细致地分析了Android系统的源代码,涉及到Linux内核层、硬件抽象层(HAL)、运行时库层(Runtime)、应用程序框架层...
Android系统的启动流程十分复杂,而`init`进程在其中扮演着至关重要的角色。本文将详细解析`init`进程的启动过程,帮助读者深入理解Android系统的核心机制。 #### 二、`init`进程概述 在Linux系统中,`init`通常是...
Android系统的启动过程是一个复杂而有序的序列,涉及多个层次的组件和交互。首先,我们从系统的引导阶段开始。 1. **系统引导 (Bootloader)** Bootloader是系统启动的第一步,它的源码位于`bootable/bootloader/`...
### Android系统启动流程源码分析 #### 一、Init 进程启动 **Init 进程**是一个由内核启动的用户级进程。当内核完成自身加载后,接下来的任务便是启动用户空间的第一个进程——`init`。此进程在Android系统中扮演...
《Android系统源代码情景分析 第3版》是深入理解Android操作系统内核与应用程序开发的一本重要参考资料。本书针对Java开发者,详细解读了Android系统的各个方面,包括系统架构、进程管理、内存管理、图形系统、网络...
在init进程的初始化过程中,最重要的一项工作是解析init.rc文件,这是一个脚本文件,用于定义系统启动时要执行的动作和服务。此外,init进程还需负责生成设备驱动节点,处理子进程的终止事件,以及提供属性服务。 3...
7. **系统启动流程**:Android系统的启动涉及bootloader、init进程、Zygote进程等。书中会阐述这个过程中的关键步骤,以及如何调试和优化启动速度。 8. **安全机制**:Android的安全模型基于权限系统,保护用户数据...
Android系统的启动过程是一个复杂而有序的系列步骤,涵盖了硬件初始化、操作系统加载以及应用程序框架的建立。下面是详细的Android启动过程分析: 1. **Bootloader阶段**: Bootloader是设备启动时运行的第一段...
《Android系统源代码分析》是一本深度探讨Android操作系统内核及其组件的专业书籍,对于从事Android应用或系统开发的工程师来说,具有极高的学习价值。这本书旨在帮助开发者理解Android系统的内部工作机制,从而提升...
Android系统启动流程 当系统引导程序启动Linux内核,内核会加载各种数据结构,和驱动程序;
2. **服务启动**:Android系统的许多服务在启动时自动运行,过度的服务启动可能导致系统资源紧张,影响用户体验。 3. **应用启动**:预置应用或用户自定义的应用启动时间也是评估启动性能的一部分,特别是一些大型...
2. **解析`/init.rc`和`/init.%hardware%.rc`文件**:`init`进程会解析这两个配置文件,这些文件定义了在系统启动过程中需要执行的各种动作和服务。 3. **执行早期初始化动作**:根据`/init.rc`中的定义,执行一...
Android 系统启动流程是一个复杂的过程,从 SystemServer 开始到 Launcher 的启动涉及到多个组件和服务的协作。本文将详细介绍 Android 系统从 SystemServer 开始的 Launcher 启动流程,并对其中的关键组件和服务...
本篇文章通过对Android系统的特性的分析,介绍了Android系统漏洞及Root工具的使用,并在证据采集过程中探讨了Root工具的应用,如获取数据、恢复删除的数据、获取系统内存镜像以及绕过启动密码等问题。 首先,需要...
《Android系统源代码情景分析》随书光盘内容(源代码) 目录如下: 第1篇 初识Android系统 第1章 准备知识 1.1 Linux内核参考书籍 1.2 Android应用程序参考书籍 1.3 下载、编译和运行Android源代码 ...
本资源"Android系统源代码情景分析-源码"旨在帮助开发者深入理解Android的工作原理,通过源码级别的学习,提升开发和调试能力。 一、Android系统架构 Android系统主要分为以下几个层次: 1. **Linux内核**:作为...