在内核初始化完成后,最后会启动第一个用户空间进程,路径名为/init,它对应的代码是在/system/core/init/init.c。

下面将从main函数开始一步步分析其中的执行过程。

if (!strcmp(basename(argv[0]), "ueventd"))

return ueventd_main(argc, argv);

if (!strcmp(basename(argv[0]), "watchdogd"))

return watchdogd_main(argc, argv);

首先,watchdog和uevent命令已经集成到了init。/sbin/ueventd和/sbin/watchdogd是一个链接文件,它直接链接到/init,所以当执行/sbin/eventd或/sbin/watchdogd时,将会进入相应的ueventd_main或watchdogd_main入口点。ueventd伺服程序将解析/ueventd.rc文件,并创建相应的设备结点。watchdogd伺服程序是一个看门狗程序,它的任务就是定期向看门狗设备文件执行写操作,以判断系统是否正常运行。

接下来就是创建几个必须的目录,并挂载tmpfs,devpts,proc,sysfs文件系统,将通过创建文件"/dev/.booting"来表示目前正处于启动中的状态。

/* clear the umask */

umask(0);

/* Get the basic filesystem setup we need put

* together in the initramdisk on / and then we'll

* let the rc file figure out the rest.

*/

mkdir("/dev", 0755);

mkdir("/proc", 0755);

mkdir("/sys", 0755);

mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "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);

/* indicate that booting is in progress to background fw loaders, etc */

close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));

接下来,将创建两个设备结点:/dev/__null__以及/dev/__kmsg__,并打开标准输入流,输出流以及错误输出流,并将它们重定向到/dev/__null__,所以,此时是不能直接调用printf系列的函数直接打印Log输出,而是利用klog输出日志。

open_devnull_stdio();

klog_init();

property_init();

接下来,property_init初始化属性服务所需要的基本空间。首先创建一个/dev/__properties__文件,然后通过对应的文件描述映射一块共享内存,大小PA_SIZE(49152),映射的地址和相应的文件描述符保存在struct workspace中。

typedef struct {

void *data;

size_t size;

int fd;

} workspace;

其中data记录了映射的共享内存的地址,而fd保存的是一个只读权限的文件描述符,size是这块映射的共享内存的大小。

接着获取硬件信息,将处理传递给内核的命令行参数

get_hardware_name(hardware, &revision);

process_kernel_cmdline();

如果启用了SELinux机制,接下来将加载selinux策略,并初始化文件安全上下文以及属性安全上下文。

union selinux_callback cb;

cb.func_log = klog_write;

selinux_set_callback(SELINUX_CB_LOG, cb);

cb.func_audit = audit_callback;

selinux_set_callback(SELINUX_CB_AUDIT, cb);

INFO("loading selinux policy\n");

if (selinux_enabled) {

if (selinux_android_load_policy() < 0) {

selinux_enabled = 0;

INFO("SELinux: Disabled due to failed policy load\n");

} else {

selinux_init_all_handles();

}

} else {

INFO("SELinux: Disabled by command line option\n");

}

/* These directories were necessarily created before initial policy load

* and therefore need their security context restored to the proper value.

* This must happen before /dev is populated by ueventd.

*/

restorecon("/dev");

restorecon("/dev/socket");

restorecon("/dev/__properties__");

如果当前启动模式不是充电模式,将从/default.prop文件中加载默认的一些属性设置。

INFO("property init\n");

if (!is_charger)

property_load_boot_defaults();

然后就是解析/init.rc文件中的一些action, service,等信息,并通过action_for_each_trigger执行相应的命令。同时queue_builtin_action也会增加一些内置的action,将在稍后逐条触发执行。

最后进入循环,逐条执行命令,并启动service_list中的所有服务,将其状态变为SVC_RUNNING, 最后将监听属性设置命令,按键请求以及信号等消息,并作相应处理。

更多相关文章

  1. QT5.2 Android(安卓)App中使用QML文件
  2. Android(安卓)在JNI中执行Java方法--C/C++调用Java
  3. Android(安卓)Studio(2.3.3)配置Kotlin笔记
  4. Android(安卓)遍历删除SD卡中某一文件夹下的指定子文件夹及其子
  5. Android(安卓)Studio 找不到R文件解决方法汇总
  6. Android(安卓)命令行构建和签署APK
  7. Android(安卓)JNI的基本使用(CMake)
  8. Android(安卓)app接收来自adb发送的广播的实例学习
  9. Android(安卓)SDK下载和更新失败的解决方法!!!

随机推荐

  1. Android(安卓)imageView图片按比例缩放
  2. android 布局学习
  3. Android界面——LinearLayout和RelativeL
  4. android 几个常用命令
  5. 通过xml加载菜单Menus
  6. Android(安卓)源代码结构
  7. Android(安卓)imageView图片按比例缩放
  8. android Wifi自动连接
  9. Android系统自带主题样式(android:theme),An
  10. Android发展史