Android系统源码分析-从init进程开始

简介 

Android系统底层用的是Linux,和Linux一样,init进程是Linux系统用户进程的第一个进程,它是由Linux内核(kenerl)启动的。其它所有的用户进程都是init进程的子进程。
我们从init进程来分析Android系统的启动流程。

 

init进程代码分析: 

init进程是被kernel中的kernel_init函数通过execve系统调用进行的初始化。

init进程的代码位置:
system/core/init/init.c 

init的main函数:

 (1) 创建并挂载文件系统相关目录,并且赋予root权限(0755); 例如,代码中的:

    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

也就是说,这些目录是在Android系统运行期间由init进程创建的,而不是在编译期间创建。 

(2)创建标准输入输出设备节点文件,即

open_devnull_stdio();

 这个函数会在/dev目录下创建__null__设备节点文件,然后,标准输入输出,标准错误输出会重定向到这个设备节点中。

(3) 简析init.rc,%hardware%.rc文件。init.rc文件是init进程启动后执行的脚本文件。在rc文件中,启动了很多守护进程,例如,服务管理器servicemanager,rild,installd......等等。init.rc它主要包含五种类型语句: 
Action、Commands、Services、Options和Import。

解析init.rc的语句是:

init_parse_config_file("/init.rc");

(4) 初始化设备id;

(5)初始化属性(property)服务;

property_init()

Android系统中的所有进程共享系统属性值,这些属性值被保存在共享内存中,通过调用 property_init()函数,来初始化属性值;

(6) 启动property服务;

(7) 循环处理device/property,进行事件处理。包括重启(restart_processes()函数)或终止子进程,并发送SIGCHLD信号等。

整个流程图如下:

init.c main函数代码:
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    /* 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));

        /* We must have some place other than / to create the
         * device nodes for kmsg and null, otherwise we won't
         * be able to remount / read-only later on.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

......

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
    ......

    return 0;
}

在文件系统创建完成后,就进入了loop循环,在循环中,进行了一系列的fd(文件描述符)的初始化和设置。这些文件fd是struct pollfd结构体类型的,主要有{ device _fd , property_set_fd , signal_recv_fd , keychord_fd }4种。

device _fd:

 主要设置包括sdcard在内的socket。

property_set_fd:

 property的cs架构:

#define PROP_SERVICE_NAME "property_service"

signal_recv_fd and signal_fd:

//signal_recv_fd and signal_fd:

/* create a signalling mechanism for the 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);
    }

……
//read signal
read(signal_recv_fd, tmp, sizeof(tmp);
while (!wait_for_one_process(0)); //阻塞

这些文件系统,socket等的初始化都ok后,其它进程会和这些资源进行进程间通信。

下面,是一个典型的进程列表:

USER     PID   PPID  VSIZE RSS   WCHAN    PC         NAME

root     1     0     548   196   c00b8c14 0000d5cc S /init

root     2     0     0     0     c006bf70 00000000 S kthreadd

......

root     724   2     0     0     c0216908 00000000 S mmcqd

root     726   1     772   180   c019dbc4 afe0c1dc S /system/bin/sh

system   727   1     840   188   c022d8a0 afe0c47c S /system/bin/servicemanager

root     729   1     1920  336   ffffffff afe0c1dc S /system/bin/mountd

root     730   1     704   176   c0257854 afe0ce0c S /system/bin/debuggerd

root     731   1     4132  628   c027e2f8 afe0ce0c S /opl/bin/tcmd

root     732   1     852   248   c00b92b0 afe0c5a4 S /opl/bin/adapter

radio    733   1     12796 648   ffffffff beaab18c S /system/bin/rild

root     734   1     72000 14172 c00b92b0 afe0c5a4 S zygote

root     735   1     33848 4512  ffffffff afe0c47c S /system/bin/mediaserver

root     736   1     1080  216   c00b8c14 bedc021c S /system/bin/dbus-daemon

root     737   1     832   208   c02b6e80 afe0c1dc S /system/bin/installd

root     740   1     856   260   c00b92b0 afe0c5a4 S /opl/bin/bpd

root     741   1     828   172   c00b8c14 afe0d27c S /opl/bin/battmond

root     768   1     720   272   c02265ec afe0c1dc S /system/bin/logcat

root     769   1     716   264   c02265ec afe0c1dc S /system/bin/logcat

root     816   2     0     0     c0068eec 00000000 S battery.0

system   825   734   574128 28360 ffffffff afe0c47c S system_server

radio    877   734   158260 20040 ffffffff afe0d404 S com.android.phone

app_5    879   734   100888 13616 ffffffff afe0d404 S android.process.acore

system   882   734   144664 24296 ffffffff afe0d404 S android.process.omsservice

app_45   884   734   92304 10932 ffffffff afe0d404 S com.motorola.motohome

app_22   890   734   117068 30228 ffffffff afe0d404 S oms.home

app_3    918   734   98760 12652 ffffffff afe0d404 S oms.widgetmanager

app_5    928   734   100888 13336 ffffffff afe0d404 S com.android.inputmethod.borqs

app_24   930   734   105176 19168 ffffffff afe0d404 S com.db4o.servo.search

app_18   960   734   104180 15208 ffffffff afe0d404 S com.android.mms

app_8    979   734   118860 14044 ffffffff afe0d404 S android.process.media

app_9    991   734   91980 12264 ffffffff afe0d404 S com.android.alarmclock

app_15   998   734   103144 12908 ffffffff afe0d404 S oms.dcd

system   1018  734   94732 13792 ffffffff afe0d404 S oms.dm

app_14   1025  734   95636 13036 ffffffff afe0d404 S com.android.calendar

app_42   1041  734   93292 11316 ffffffff afe0d404 S com.motorola.smsautoreg

app_40   1090  734   97152 15192 ffffffff afe0d404 S com.motorola.mtc

app_38   1102  734   93832 12868 ffffffff afe0d404 S com.streamezzo.browser.android

app_26   1115  734   96596 15084 ffffffff afe0d404 S oms.mediacenter

app_37   1126  734   98208 15212 ffffffff afe0d404 S com.hyfsoft.docviewer

app_20   1146  734   99260 15320 ffffffff afe0d404 S com.android.music

app_47   1157  734   100204 15964 ffffffff afe0d404 S com.motorola.camera

app_11   1183  734   122672 23576 ffffffff afe0d404 S com.android.browser

app_6    1199  734   117032 20388 ffffffff afe0d404 S oms.mobilemusic

system   1244  734   99292 15940 ffffffff afe0d404 S com.android.settings

app_23   1311  734   96932 16004 ffffffff afe0d404 S oms.bru

root     1334  2     0     0     c0216908 00000000 S mmcqd

app_8    1351  734   100308 15876 ffffffff afe0d404 S com.android.camera

app_1    1424  734   111904 17024 ffffffff afe0d404 S oms.messaging

app_4    1436  734   101172 15504 ffffffff afe0d404 S oms.mail

app_2    1484  734   100716 18128 ffffffff afe0d404 S com.ms

app_16   1663  734   101024 16748 ffffffff afe0d404 S oms.android.filemanager

root     1684  1     3364  176   ffffffff 0000e8f4 S /sbin/adbd

root     1692  1684  776   348   c0059cd4 afe0d0ac S /system/bin/sh

root     1724  1692  920   356   00000000 afe0c1dc R ps

可见,所有的进程都是init的子进程。
列举几个重要的进程:
servicemanager:所有的服务都要最终注册在这个进程中,有它来进行管理这些服务。
rild:发短信,打电话等应用,会和rild进行通信,而rild再和baseband模块进行通信,从而实现发短信,打电话功能。
zygote:Android系统中最重要的进程,所有的上层应用都是它孵化出来的。
system_server:即Android framework所在的进程。包括一系列框架服务,例如,PackageManager,ActivityManager,BatteryManager...等等。

init.rc:

init.rc部分代码截取: 

import /init.${ro.hardware}.rc
import /init.usb.rc
import /init.trace.rc

on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_adj -16

    start ueventd

# create mountpoints
    mkdir /mnt 0775 root system

on init

sysclktz 0

loglevel 3

# setup the global environment
    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
    export LD_LIBRARY_PATH /vendor/lib:/system/lib
    export ANDROID_BOOTLOGO 1
    export ANDROID_ROOT /system
    export ANDROID_ASSETS /system/app
    export ANDROID_DATA /data

......

    mkdir /system
    mkdir /data 0771 system system
    mkdir /cache 0770 system cache
    mkdir /config 0500 root root

......

## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd
    class core
    critical

service console /system/bin/sh
    class core
    console
    disabled
    user shell
    group log

on property:ro.debuggable=1
    start console

# adbd is controlled via property triggers in init.<platform>.usb.rc
service adbd /sbin/adbd
    class core
    disabled

# adbd on at boot in emulator
on property:ro.kernel.qemu=1
    start adbd

service servicemanager /system/bin/servicemanager
    class core
    user system
    group system

......

 分析:

1. 在init.rc中,创建了系统需要的系统文件夹,例如/system, /data, 并赋予相应的权限。

2. 设置了全局环境变量,例如

export ANDROID_ROOT /system
export ANDROID_ASSETS /system/app
export ANDROID_DATA /data

3. 用service指令启动了很多守护进程,例如,ueventd,sh,adbd,servicemanager......等。从底层架构的角度来看,正是这些守护进程,对上提供了丰富的功能,对下层,大部分守护进程都是通过系统调用去与kenel进行交互,从而实现在整个系统中,能够进行进程间的通信。


了解底层的运作机制,对于理解上层代码,乃至整个系统,都非常有益。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值