精华内容
参与话题
问答
  • init进程

    2016-03-16 17:15:14
     init进程,是内核启动的第一个用户级进程。init有许多很重要的任务,比如象启动getty(用于用户登录)、实现运行级别、以及处理孤立进程。  对于Linux系统的运行来说,init程序是最基本的程序之一。但你仍可以大...

           介绍

           init进程,是内核启动的第一个用户级进程。init有许多很重要的任务,比如象启动getty(用于用户登录)、实现运行级别、以及处理孤立进程。

      对于Linux系统的运行来说,init程序是最基本的程序之一。但你仍可以大部分的忽略它。一个好的Linux发行版本通常随带有一个init的配置,这个配置适合于绝大多数系统的工作,在这样一些系统上不需要对init做任何事。通常,只有你在碰到诸如串行终端挂住了、拨入(不是拨出)调制解调器、或者你希望改变缺省的运行级别时你才需要关心init。

      当内核启动了自己之后(已被装入内存、已经开始运行、已经初始化了所有的设备驱动程序和数据结构等等),通过启动用户级程序init来完成引导进程的内核部分。因此,init总是第一个进程(它的进程号总是1)。

      内核在几个位置上来查寻init,这几个位置以前常用来放置init,但是init的最适当的位置(在Linux系统上)是/sbin/init。如果内核没有找到init,它就会试着运行/bin/sh,如果还是失败了,那么系统的启动就宣告失败了。

      当init开始运行,它通过执行一些管理任务来结束引导进程,例如检查文件系统、清理/tmp、启动各种服务以及为每个终端和虚拟控制台启动getty,在这些地方用户将登录系统。

      在系统完全起来之后,init为每个用户已退出的终端重启getty(这样下一个用户就可以登录)。init同样也收集孤立的进程:当一个进程启动了一个子进程并且在子进程之前终止了,这个子进程立刻成为init的子进程。对于各种技术方面的原因来说这是很重要的,知道这些也是有好处的,因为这便于理解进程列表和进程树图。init的变种很少。绝大多数Linux发行版本使用sysinit(由Miguel van Smoorenburg著),它是基于System V的init设计。UNIX的BSD版本有一个不同的init。最主要的不同在于运行级别:System V有而BSD没有(至少是传统上说)。

      启动(引导)进入单用户模式

      一个很重要的运行级别是单用户模式(single user mode)(运行级别1),在这个模式中只有系统管理员在使用机器并且只有很少的系统服务在运行,如登录服务。对于一些管理任务来说单用户模式是必须的,如在/usr分区上运行fsck,因为这需要该分区没被加载,除非几乎所有的系统服务都被终止了,否则不可能会有这种情况。通过telinit请求运行级别1,一个运行着的系统可以转换到单用户模式。在启动时,可以通过在内核的命令行上给出single或emergency来进入单用户模式:内核同样也将命令行给init,init会理解那个单词并且不会使用缺省的运行级别。(内核命令行输入的方法依赖于系统是如何引导的。)在加载文件系统之前,引导进入单用户模式有时是需要的,这样就可以手工运行fsck命令了,否则的话很可能损坏/usr分区(在一个有问题的文件系统上的任何操作会更进一步地损坏它,所以fsck要尽早地运行)。如果启动时fsck的自动检查失败了,启动描述文件init就会自动地进入单用户模式。这是试图避免系统使用一个文件系统,这个文件系统损坏的太严重以至于fsck都不能够自动地修复它。这样的毁坏情况是相当少的,通常是硬盘有问题或是在试验一个内核版本,但是有准备总比没有好。作为一个安全措施,一个正确配置的系统应该在运行单用户模式的shell之前要求口令。否则的话,只要给LILO输入适当的一行参数就很容易地以root身份进入系统。(当然,如果由于文件系统的问题而使/etc/passwd毁坏时,就不是这样了。如果是这样的话,你手头最好有张引导软盘。)

           启动顺序

           启动Init进程,其实质是执行/sbin/init程序,即Init进程可以启动其它子进程,或启动shell,本质上是因为内核执行了可执行序/sbin/init.因此,可以说Init进程的作用只不过是可执行程序/sbin/init的作用.可以这样来理解,当执行可执行程序/sbin/init时,该程序就是一进程,名字是Init.当然,用户也可以根据需要编写自己的/sbin/init程序,或者传入命令行参数"init=xxxx"指定某个程序作为Init进程运行.在嵌入式领域内,一般来说多使用Busybox集成的Init程序.

             内核启动的最后一步就是启动Init进程.该Init进程中,它主要做了以下几项工作:
       <1>读取系统初始化表格文件/etc/inittab.(BusyBox init及inittabl文件
       <2>建立getty进程,在终端上显示login提示符,以等待用户的登录.
       <3>进程getty会调用exec以执行login程序.该程序将会核对用户账号和密码.
       <4>login程序会调用exec以执行shell命令解释器,也可执行X-windows.
       <5>shell命令解释器会读取系统环境配置脚本/etc/profile.

    展开全文
  • Init进程

    2015-04-16 19:27:37
    init进程之间是内核启动的第一个用户态进程,而start_kernel()是内核汇编和c语言的连接点,在该函数之前,汇编代码会完成一些初始化,比如为c语言准备运行环境,此函数就像c程序的main函数一样。 init/main.c中,...

    李峰

    原创作品转载请注明出处

    《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

    linux启动流程

    从计算机上电开始到内核加载:

    计算机如何启动
    计算机如何启动1

    从内核加载到用户登录如下图,

    init(为英语:initialization的简写)是 Unix 和 类Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为1。
    ——— [维基百科]
    Upstart是一个基于事件的初始化守护进程,用于替代传统的init(多种类Unix计算机操作系统启动时用于执行任务的程序)。——— [维基百科]

    Linux启动流程
    Linux启动流程2

    init进程是什么

    init进程是一个普通的用户态进程,特别之处在于它是所有进程的祖宗。它是内核初始化和用户态初始化的结合点,在内核初始化的结尾部分,init进程被启动,然后开始用户态的初始化。

    init进程受什么控制

    init进程运行完全受/etc/inittab的控制,如果你要追踪内核的初始化,则从init/main.c文件中的start_kernel()函数开始,如果你要追踪用户态的初始化,则要从/etc/rc.d/rc.sysinit脚本开始。

    init进程怎么启动的

    init进程是内核启动的第一个用户态进程,而start_kernel()是内核汇编和c语言的连接点,在该函数之前,汇编代码会完成一些初始化,比如为c语言准备运行环境,此函数就像c程序的main函数一样。
    init/main.c中,start_kernel()是内核的入口,在该函数的最后一行,执行了rest_init();,这个函数里通过函数kernel_thread(kernel_init, NULL, CLONE_FS);创建了一个内核线程,该线程会运行static int __ref kernel_init(void *unused)函数,在该函数的结尾处,有如下代码:

    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return 0;

    这段代码即创建了init process,首先运行/sbin/init,如果失败则运行/etc/init,如果又失败则运行/bin/init,然后是/bin/sh,该函数运行完成以后,init process就被创建,预示着内核初始化结束,用户态初始化开始。

    start_kernel函数
    start_kernel函数3

    kernel_thread如何创建内核线程的呢?

    kernel_thread函数如下:

    pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
    {
        return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
            (unsigned long)arg, NULL, NULL);
    }

    第一个参数即kernel_init函数的地址,为此进程执行时需要执行的函数,此函数返回值为int型,参数是一个void 指针,穿进去的第二个参数是此函数的参数,这里实际值设置为NULL, 第三个参数是创建新进程的标志位,在内核中有定义,这里实际取CLONE_FS ,宏定义如下:#define CLONE_FS 0x00000200 /* set if fs info shared between processes */。此函数返回pid_t变量,即新创建的进程的进程号。
    函数内部调用了do_fork函数,函数分析见:do_fork分析,下面分析此函数的关键代码:

    p = copy_process(clone_flags, stack_start, stack_size,
                 child_tidptr, NULL, trace);

    copy_process函数创建一个和原来进程一摸一样的进程,复制了原来进程用到的寄存器,和相应的进程环境。然后返回struct task_struct指针,即进程描述符,函数分析见窥探 kernel — copy_process

    kernel_thread()
    kernel_thread()函数

    进程的切换机制

    进程切换统一发生在schedule(void)函数中,核心函数是__schedule(void),函数分析见 schedule()函数篇

    展开全文
  • Android系统init进程启动及init.rc全解析

    万次阅读 多人点赞 2017-11-23 16:14:40
    system/core/init/init.c文件main函数中parse_config_file(init.rc)读取并解析init.rc文件内容。将service信息放置到system/core/init/init_parser.cpp的service_list中 system/core/init/init.c文

    这是一篇用心写的博客,也希望大家用心看并帮忙找到文章的改进之处,谢谢;

    服务启动机制

    1. system/core/init/init.c文件main函数中parse_config_file(init.rc)读取并解析init.rc文件内容。将service信息放置到system/core/init/init_parser.cpp的service_list中
    2. system/core/init/init.c文件main函数继续执行restart_servie_if_needed(…) -> service_start(…) -> Execve(…)建立service进程;

    为了让大伙看得更明白,上个图先《总体启动框架图》:
    这里写图片描述

    init.rc 简介

    目前Linux有很多通讯机制可以在用户空间和内核空间之间交互,例如设备驱动文件(位于/dev目录中)、内存文件(/proc、/sys目录等)。了解Linux的同学都应该知道Linux的重要特征之一就是一切都是以文件的形式存在的,例如,一个设备通常与一个或多个设备文件对应。这些与内核空间交互的文件都在用户空间,所以在Linux内核装载完,需要首先建立这些文件所在的目录。而完成这些工作的程序就是本文要介绍的init。Init是一个命令行程序。其主要工作之一就是建立这些与内核空间交互的文件所在的目录。当Linux内核加载完后,要做的第一件事就是调用init程序,也就是说,init是用户空间执行的第一个程序。

    尽管init完成的工作不算很多,不过代码还是非常复杂的。Init程序并不是由一个源代码文件组成的,而是由一组源代码文件的目标文件链接而成的。这些文件位于如下的目录。

    需要明白的是,这些init.rc只是语法文件,并不是程序,真正的入口则是上面提到的system/core/init/init.c
    因为init.c文件比较大,在文章的第二部分我会简要的通过main函数分析init启动流程;

    init.rc有两个,分别位于:
    ./system/core/rootdir/init.rc
    ./bootable/recovery/etc/init.rc
    从目录上大致可以猜测,这两个init.rc使用场景不一样,一个是刷机用到的,也就是进入recorvery模式,一个是正常启动用到的;我们这里重点分析的是上面那个,也是init.c关联的那个;

    init.rc语法结构解析

    要了解init.rc是怎么解析的,我们需要先看看说明文档,说明文档在,当然也可以看下热心网友的中文对照版本
    init.rc位于/bootable/recovery/etc/init.rc

    Android初始化语言包含了四种类型的声明:
    Actions(行为)、Commands(命令)、Services(服务)和Options(选项)

    所有这些都是以行为单位的,各种记号由空格来隔开。
    C语言风格的反斜杠号可用于在记号间插入空格。
    双引号也可用于防止字符串被空格分割成多个记号。
    行末的反斜杠用于折行,注释行以井号(#)开头(允许以空格开头)。

    需要注意的是,这个只是一个语法文件,就像一个xml文件一样,没有执行顺序的,解析器通过读这个文件获取想要的数据,包括service,action等

    Actions和Services声明一个新的分组Section。所有的命令或选项都属于最近声明的分组。位于第一个分组之前的命令或选项将会被忽略。
    Actions和Services有唯一的名字。如果有重名的情况,第二个申明的将会被作为错误忽略。

    Actions

    Actions(行为)是一系列命令的开始
    Actions代表一些Action.Action代表一组命令(Commands),Actions都有一个trigger(触发器),该触发器决定了何时执行这个Action,即在什么情况下才能执行该Action中的定义命令.当一些条件满足触发器的条件时,该Action中定义的命令会被添加到要执行命令队列的尾部(如果这组命令已经在队列中,则不会再次添加).

    队列中的每一个action都被依次提取出,而这个action中的每个command(命令)在一个Action从队列移除时,该Action定义的命令会依次被执行.

    Action的格式如下:

    on <trgger> [&& <trigger>]*
       <command1>
       <command2>
       <command3>
       ...
    

    on后面跟着一个触发器,当trigger被触发时,command1,command2,command3,会依次执行,直到下一个Action或下一个Service。

    简单来说,Actions就是Android在启动时定义的一个启动脚本,当条件满足时,会执行该脚本,脚本里都是一些命令commands,不同的脚本用on来区分。

    ###Triggers(触发器)
    trigger即我们上面所说的触发器,本质上是一个字符串,能够匹配某种包含该字符串的事件.
    trigger又被细分为事件触发器(event trigger)和属性触发器(property trigger).
    Triggers(触发器)是一个用于匹配特定事件类型的字符串,用于使Actions发生。

    事件触发器可由"trigger"命令或初始化过程中通过QueueEventTrigger()触发,通常是一些事先定义的简单字符串,例如:boot,late-init
    属性触发器是当指定属性的变量值变成指定值时触发,其格式为property:=*

    一个Action可以有多个属性触发器,但是最多有一个事件触发器.下面我们看两个例子:

    on boot && property:a=b
    

    该Action只有在boot事件发生时,并且属性a和b相等的情况下才会被触发.

    on property:a=b && property:c=d
    

    该Action会在以下三种情况被触发:

    • 在启动时,如果属性a的值等于b并且属性c的值等于d
    • 在属性c的值已经是d的情况下,属性a的值被更新为b
    • 在属性a的值已经是b的情况下,属性c的值被更新为d

    当前AIL中常用的有以下几种事件触发器:

    类型						说明
    -------------------------------------------------
    boot					init.rc被装载后触发
    device-added-<path>		指定设备被添加时触发
    device-removed-<path>	指定设备被移除时触发
    service-exited-<name>	在特定服务(service)退出时触发
    early-init				初始化之前触发
    late-init				初始化之后触发
    init					初始化时触发(在 /init.conf (启动配置文件)被装载之后)
    

    Init的触发是由init.c里的函数action_for_each_trigger来决定的(在main函数中被调用)。

    Services

    Services(服务)是一个程序,以 service开头,由init进程启动,一般运行于另外一个init的子进程,所以启动service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service,在启动时会通过fork方式生成子进程。Services(服务)的形式如下:

    service <name> <pathname> [ <argument> ]*
        <option>
        <option>
        ...
    

    其中:

    • name:服务名
    • pathname:当前服务对应的程序位置
    • option:当前服务设置的选项
    • argument 可选参数

    init.rc文件详解

    为了方便理解,我把整个init.rc解析一边,便于大家了解整个流程;如果想要了解recovery下的init语法解析,参考这篇文章《recovery下的init.rc语法解析》
    代码量比较大,如果觉得看起来费劲,可以挑绿色部分看;

    # Copyright (C) 2012 The Android Open Source Project
    #
    # IMPORTANT: Do not create world writable files or directories.
    # This is a common source of Android security bugs.
    #
    
    "【import <filename>一个init配置文件,扩展当前配置。】"
    import /init.environ.rc
    import /init.usb.rc
    import /init.${ro.hardware}.rc
    import /init.${ro.zygote}.rc
    import /init.trace.rc
    
    "【触发条件early-init,在early-init阶段调用以下行】"
    on early-init
        # Set init and its forked children's oom_adj.
        write /proc/1/oom_score_adj -1000
    	"【打开路径为<path>的一个文件,并写入一个或多个字符串】"
        # Apply strict SELinux checking of PROT_EXEC on mmap/mprotect calls.
        write /sys/fs/selinux/checkreqprot 0
    
        # Set the security context for the init process.
        # This should occur before anything else (e.g. ueventd) is started.
        "【这段脚本的意思是init进程启动之后就马上调用函数setcon将自己的安全上下文设置为“u:r:init:s0”,即将init进程的domain指定为init。】"
        setcon u:r:init:s0
    
        # Set the security context of /adb_keys if present.
        "【恢复指定文件到file_contexts配置中指定的安全上线文环境】"
        restorecon /adb_keys
    
    	"【执行start ueventd的命令。ueventd是一个service后面有定义】 "
        start ueventd
    
    	"【mkdir <path> [mode] [owner] [group]   //创建一个目录<path>,可以选择性地指定mode、owner以及group。如果没有指定,默认的权限为755,并属于root用户和root组。】"
        # create mountpoints
        mkdir /mnt 0775 root system
    
    on init
    	"【设置系统时钟的基准,比如0代表GMT,即以格林尼治时间为准】"
        sysclktz 0
    
    "【设置kernel日志等级】"
    loglevel 6 ####
        write /proc/bootprof "INIT: on init start" ####
    	
    	"【symlink <target> <path>    //创建一个指向<path>的软连接<target>。】"
        # Backward compatibility
        symlink /system/etc /etc
        symlink /sys/kernel/debug /d
    
        # Right now vendor lives on the same filesystem as system,
        # but someday that may change.
        symlink /system/vendor /vendor
    
    	"【创建一个目录<path>,可以选择性地指定mode、owner以及group。】"
        # Create cgroup mount point for cpu accounting
        mkdir /acct
        mount cgroup none /acct cpuacct
        mkdir /acct/uid
    
    	"【mount <type> <device> <dir> [ <mountoption> ]   //在目录<dir>挂载指定的设备。<device> 可以是以 mtd@name 的形式指定一个mtd块设备。<mountoption>包括 ro、rw、remount、noatime、 ...】"
        # Create cgroup mount point for memory
        mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000
        mkdir /sys/fs/cgroup/memory 0750 root system
        mount cgroup none /sys/fs/cgroup/memory memory
        write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
        "【chown <owner> <group> <path>   //改变文件的所有者和组。】"
        
        "【后面的一些行因为类似,就省略了】"
        .....
    
    # Healthd can trigger a full boot from charger mode by signaling this
    # property when the power button is held.
    on property:sys.boot_from_charger_mode=1
    	"【停止指定类别服务类下的所有已运行的服务】"
        class_stop charger
        "【触发一个事件,将该action排在某个action之后(用于Action排队)】"
        trigger late-init
    
    # Load properties from /system/ + /factory after fs mount.
    on load_all_props_action
    	"【从/system,/vendor加载属性。默认包含在init.rc】"
        load_all_props
    
    # Indicate to fw loaders that the relevant mounts are up.
    on firmware_mounts_complete
    	"【删除指定路径下的文件】"
        rm /dev/.booting
    
    # Mount filesystems and start core system services.
    on late-init
    	"【触发一个事件。用于将一个action与另一个 action排列。】"
        trigger early-fs
        trigger fs
        trigger post-fs
        trigger post-fs-data
    
        # Load properties from /system/ + /factory after fs mount. Place
        # this in another action so that the load will be scheduled after the prior
        # issued fs triggers have completed.
        trigger load_all_props_action
    
        # Remove a file to wake up anything waiting for firmware.
        trigger firmware_mounts_complete
    
        trigger early-boot
        trigger boot
    
    
    on post-fs
    	...
        "【一些创造目录,建立链接,更改权限的操作,这里省略】"
    
    on post-fs-data
    	...
    	"【一些创造目录,建立链接,更改权限的操作,这里省略】"
    
    	"【恢复指定文件到file_contexts配置中指定的安全上线文环境】"
        restorecon /data/mediaserver
    
    	"【将系统属性<name>的值设置为<value>,即以键值对的方式设置系统属性】"
        # Reload policy from /data/security if present.
        setprop selinux.reload_policy 1
    
    	"【以递归的方式恢复指定目录到file_contexts配置中指定的安全上下文中】"
        # Set SELinux security contexts on upgrade or policy update.
        restorecon_recursive /data
    
        # If there is no fs-post-data action in the init.<device>.rc file, you
        # must uncomment this line, otherwise encrypted filesystems
        # won't work.
        # Set indication (checked by vold) that we have finished this action
        #setprop vold.post_fs_data_done 1
    
    on boot
    	"【初始化网络】"
        # basic network init
        ifup lo
        "【设置主机名为localhost】"
        hostname localhost
        "【设置域名localdomain】"
        domainname localdomain
    
    	"【设置资源限制】"
        # set RLIMIT_NICE to allow priorities from 19 to -20
        setrlimit 13 40 40
    
    	"【这里省略了一些chmod,chown,等操作,不多解释】"
       ...
       
    
        # Define default initial receive window size in segments.
        setprop net.tcp.default_init_rwnd 60
    	
    	"【重启core服务】"
        class_start core
    
    on nonencrypted
        class_start main
        class_start late_start
    
    on property:vold.decrypt=trigger_default_encryption
        start defaultcrypto
    
    on property:vold.decrypt=trigger_encryption
        start surfaceflinger
        start encrypt
    
    on property:sys.init_log_level=*
        loglevel ${sys.init_log_level}
    
    on charger
        class_start charger
    
    on property:vold.decrypt=trigger_reset_main
        class_reset main
    
    on property:vold.decrypt=trigger_load_persist_props
        load_persist_props
    
    on property:vold.decrypt=trigger_post_fs_data
        trigger post-fs-data
    
    on property:vold.decrypt=trigger_restart_min_framework
        class_start main
    
    on property:vold.decrypt=trigger_restart_framework
        class_start main
        class_start late_start
    
    on property:vold.decrypt=trigger_shutdown_framework
        class_reset late_start
        class_reset main
    
    on property:sys.powerctl=*
        powerctl ${sys.powerctl}
    
    # system server cannot write to /proc/sys files,
    # and chown/chmod does not work for /proc/sys/ entries.
    # So proxy writes through init.
    on property:sys.sysctl.extra_free_kbytes=*
        write /proc/sys/vm/extra_free_kbytes ${sys.sysctl.extra_free_kbytes}
    
    # "tcp_default_init_rwnd" Is too long!
    on property:sys.sysctl.tcp_def_init_rwnd=*
        write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd}
    
    "【守护进程】"
    ## Daemon processes to be run by init.
    ##
    service ueventd /sbin/ueventd
        class core
        critical
        seclabel u:r:ueventd:s0
    
    "【日志服务进程】"
    service logd /system/bin/logd
        class core
        socket logd stream 0666 logd logd
        socket logdr seqpacket 0666 logd logd
        socket logdw dgram 0222 logd logd
        seclabel u:r:logd:s0
    
    "【Healthd是android4.4之后提出来的一种中介模型,该模型向下监听来自底层的电池事件,向上传递电池数据信息给Framework层的BatteryService用以计算电池电量相关状态信息】"
    service healthd /sbin/healthd
        class core
        critical
        seclabel u:r:healthd:s0
    
    "【控制台进程】"
    service console /system/bin/sh
    	"【为当前service设定一个类别.相同类别的服务将会同时启动或者停止,默认类名是default】"
        class core
        "【服务需要一个控制台】"
        console
        "【服务不会自动启动,必须通过服务名显式启动】"
        disabled
        "【在执行此服务之前切换用户名,当前默认的是root.自Android M开始,即使它要求linux capabilities,也应该使用该选项.很明显,为了获得该功能,进程需要以root用户运行】"
        user shell
        seclabel u:r:shell:s0
    
    on property:ro.debuggable=1
        start console
    
    # adbd is controlled via property triggers in init.<platform>.usb.rc
    service adbd /sbin/adbd --root_seclabel=u:r:su:s0
        class core
        "【创建一个unix域下的socket,其被命名/dev/socket/<name>. 并将其文件描述符fd返回给服务进程.其中,type必须为dgram,stream或者seqpacke,user和group默认是0.seclabel是该socket的SELLinux的安全上下文环境,默认是当前service的上下文环境,通过seclabel指定】"
        socket adbd stream 660 system system
        disabled
        seclabel u:r:adbd:s0
    
    # adbd on at boot in emulator
    on property:ro.kernel.qemu=1
        start adbd
    
    "【内存管理服务,内存不够释放内存】"
    service lmkd /system/bin/lmkd
        class core
        critical
        socket lmkd seqpacket 0660 system system
    
    "【ServiceManager是一个守护进程,它维护着系统服务和客户端的binder通信。
    在Android系统中用到最多的通信机制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驱动程序组成。其中Client、Service和ServiceManager运行在用户空间,而Binder驱动程序运行在内核空间。核心组件就是Binder驱动程序了,而ServiceManager提供辅助管理的功能,无论是Client还是Service进行通信前首先要和ServiceManager取得联系。而ServiceManager是一个守护进程,负责管理Server并向Client提供查询Server的功能。】"
    service servicemanager /system/bin/servicemanager
        class core
        user system
        group system
        critical
        onrestart restart healthd
        "【servicemanager 服务启动时会重启zygote服务】"
        onrestart restart zygote
        onrestart restart media
        onrestart restart surfaceflinger
        onrestart restart drm
    
    "【Vold是Volume Daemon的缩写,它是Android平台中外部存储系统的管控中心,是管理和控制Android平台外部存储设备的后台进程】"
    service vold /system/bin/vold
        class core
        socket vold stream 0660 root mount
        ioprio be 2
    
    "【Netd是Android系统中专门负责网络管理和控制的后台daemon程序】"
    service netd /system/bin/netd
        class main
        socket netd stream 0660 root system
        socket dnsproxyd stream 0660 root inet
        socket mdns stream 0660 root system
        socket fwmarkd stream 0660 root inet
    
    "【debuggerd是一个daemon进程,在系统启动时随着init进程启动。主要负责将进程运行时的信息dump到文件或者控制台中】"
    service debuggerd /system/bin/debuggerd
        class main
    
    service debuggerd64 /system/bin/debuggerd64
        class main
    
    "【Android RIL (Radio Interface Layer)提供了Telephony服务和Radio硬件之间的抽象层】"
    # for using TK init.modem.rc rild-daemon setting
    #service ril-daemon /system/bin/rild
    #    class main
    #    socket rild stream 660 root radio
    #    socket rild-debug stream 660 radio system
    #    user root
    #    group radio cache inet misc audio log
    
    "【提供系统 范围内的surface composer功能,它能够将各种应用 程序的2D、3D surface进行组合。】"
    service surfaceflinger /system/bin/surfaceflinger
        class core
        user system
        group graphics drmrpc
        onrestart restart zygote
    
    "【DRM可以直接访问DRM clients的硬件。DRM驱动用来处理DMA,内存管理,资源锁以及安全硬件访问。为了同时支持多个3D应用,3D图形卡硬件必须作为一个共享资源,因此需要锁来提供互斥访问。DMA传输和AGP接口用来发送图形操作的buffers到显卡硬件,因此要防止客户端越权访问显卡硬件。】"
    #make sure drm server has rights to read and write sdcard ####
    service drm /system/bin/drmserver
        class main
        user drm
        # group drm system inet drmrpc ####
        group drm system inet drmrpc sdcard_r ####
    
    "【媒体服务,无需多说】"
    service media /system/bin/mediaserver
        class main
        user root ####
    #   google default ####
    #   user media    ####
        group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm media sdcard_r system net_bt_stack ####
    #   google default ####
    #   group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ####
    
        ioprio rt 4
    
    "【设备加密相关服务】"
    # One shot invocation to deal with encrypted volume.
    service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted
        disabled
        "【当服务退出时,不重启该服务】"
        oneshot
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption) or trigger_restart_min_framework (other encryption)
    
    # One shot invocation to encrypt unencrypted volumes
    service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default
        disabled
        oneshot
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption)
    
    "【开机动画服务】"
    service bootanim /system/bin/bootanimation
        class core
        user graphics
    #    group graphics audio ####
        group graphics media audio ####
        disabled
        oneshot
    
    "【在Android系统中,PackageManagerService用于管理系统中的所有安装包信息及应用程序的安装卸载,但是应用程序的安装与卸载并非PackageManagerService来完成,而是通过PackageManagerService来访问installd服务来执行程序包的安装与卸载的。】"
    service installd /system/bin/installd
        class main
        socket installd stream 600 system system
    
    service flash_recovery /system/bin/install-recovery.sh
        class main
        seclabel u:r:install_recovery:s0
        oneshot
    
    "【vpn相关的服务】"
    service racoon /system/bin/racoon
        class main
        socket racoon stream 600 system system
        # IKE uses UDP port 500. Racoon will setuid to vpn after binding the port.
        group vpn net_admin inet
        disabled
        oneshot
    
    "【android中有mtpd命令可以连接vpn】"
    service mtpd /system/bin/mtpd
        class main
        socket mtpd stream 600 system system
        user vpn
        group vpn net_admin inet net_raw
        disabled
        oneshot
    
    service keystore /system/bin/keystore /data/misc/keystore
        class main
        user keystore
        group keystore drmrpc
    
    "【可以用dumpstate 获取设备的各种信息】"
    service dumpstate /system/bin/dumpstate -s
        class main
        socket dumpstate stream 0660 shell log
        disabled
        oneshot
    
    "【mdnsd 是多播 DNS 和 DNS 服务发现的守护程序。】"
    service mdnsd /system/bin/mdnsd
        class main
        user mdnsr
        group inet net_raw
        socket mdnsd stream 0660 mdnsr inet
        disabled
        oneshot
    
    "【触发关机流程继续往下走】"
    service pre-recovery /system/bin/uncrypt
        class main
        disabled
        "【当服务退出时,不重启该服务】"
        oneshot
    
    

    init.c全解析

    接下来我们具体分析以下这个main函数的执行过程;可能比较长,大家耐心看一下:

     
    int main( int argc, char **argv )
    {
    	#创 建一些linux根文件系统中的目录
    	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 );
    	#init的 标准输入,标准输出,标准错误文件描述符定向到__null__,意味着没有输入和输出,它的输入和输出全部写入到Log中
    	open_devnull_stdio();
    	#初始化 log 写入init进 信息
    	log_init();
    	#读取并 且解析init.rc文件(这个文件在根目录下)
    	parse_config_file( "/init.rc" );
    	#取得硬件 为打印我们的设备名fs100
    	get_hardware_name();
    	snprintf( tmp, sizeof(tmp), "/init.%s.rc", hardware );
        #读取并 且解析硬件相关的init脚本文件,
    	parse_config_file( tmp );
    	#触发在init脚本文件中名字为early-init的action,并且执行其commands,其实是: on early-init
    	action_for_each_trigger( "early-init", action_add_queue_tail );
    	drain_action_queue();
    	#初始化动态设备管理,设备文件有变化时反应给内核,后面具体解释
    	device_fd = device_init(); # 初 始 化 设 备 管 理 务
    	#加载启动动画,如果动画打开失败,则在屏幕上打印: A N D R O I D字样。
    	if ( load_565rle_image( INIT_IMAGE_FILE ) )
    	{
    		fd = open( "/dev/tty0", O_WRONLY );
    		if ( fd >= 0 )
    		{
    			const char *msg;
    			msg = "\n"
    			      "\n"
    			      "\n"
    			      879         "\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 ";开机动画 */
    			      write( fd, msg, strlen( msg ) );
    			close( fd );
    		}
    	}
    
    	#触发 在init脚本文件中名字为init的action,并且执行其commands,其实是:on init
    	action_for_each_trigger( "init", action_add_queue_tail );
    	drain_action_queue();
    	#启动系统属性服务: system property service
    	property_set_fd = start_property_service();
    	#创建socket用来处理孤儿进程信号
    	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 );
    	}
    	#触发 在init脚本文件中名字为early-boot和boot的action,并且执行其commands,其实是:on early-boot和on boot
    	action_for_each_trigger( "early-boot", action_add_queue_tail );
    	action_for_each_trigger( "boot", action_add_queue_tail );
    	drain_action_queue();
    	#启动所有属性变化触发命令,其实是: on property:ro.xx.xx=xx
    	queue_all_property_triggers();
    	drain_action_queue();
    	#进入 死循环()
    	for (;; )
    	{
    	#启 动所有init脚本中声明的service,
    	#如 :266 service servicemanager /system/bin/servicemanager
    	#user system
    	#critical
    	#onrestart restart zygote
    	#onrestart restart media
    	restart_processes();
    	#多路监听设备管理,子进程运行状态,属性服务
    		nr = poll( ufds, fd_count, timeout );
    		if ( nr <= 0 )
    			continue;
    		if ( ufds[2].revents == POLLIN )
    		{
    			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);
    }
    
    
    展开全文
  • 关于父进程先于子进程终止后,子进程应该由init进程收养,所以子进程的ppid不应该是1吗?但我用C语言查看时显示的确是另一个进程id:1795 #include #include #include #include int main(void) { ...
  • Android init进程启动

    万次阅读 2012-07-12 23:30:38
    一、Android Init.c执行流程Android中的内核启动后,kernel会启动第一个用户级别的进程init,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构...

    一、Android Init.c执行流程

    Android中的内核启动后,kernel会启动第一个用户级别的进程:init,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。
    PS:可以通过:ps aux | grep init命令来查看其Pid为1。
    init进程对应的代码在android源码目录中的:system/core/init/init.c中。
    789 int main(int argc, char **argv)
    790 {
    # 创建一些linux根文件系统中的目录
    817     mkdir("/dev", 0755);
    818     mkdir("/proc", 0755);
    819     mkdir("/sys", 0755);
    820
    821     mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
    822     mkdir("/dev/pts", 0755);
    823     mkdir("/dev/socket", 0755);
    824     mount("devpts", "/dev/pts", "devpts", 0, NULL);
    825     mount("proc", "/proc", "proc", 0, NULL);
    826     mount("sysfs", "/sys", "sysfs", 0, NULL); 
    # init的标准输入,标准输出,标准错误文件描述符定向到__null__,意味着没有输入和输出,它的输入和输出全部写入到Log中
    834     open_devnull_stdio();

    # 初始化log,写入init进程信息

    835     log_init();
    # 读取并且解析init.rc文件
    838     parse_config_file("/init.rc");
    # 取得硬件名
    844     get_hardware_name();
    845     snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    # 读取并且解析硬件相关的init脚本文件
    846     parse_config_file(tmp);
    # 触发在init脚本文件中名字为early-init的action,并且执行其commands,其实是: on early-init
    848     action_for_each_trigger("early-init", action_add_queue_tail);
    849     drain_action_queue();
    # 初始化动态设备管理,设备文件有变化时反应给内核,后面具体解释
    852     device_fd = device_init();
    # 加载启动动画,如果动画打开失败,则在屏幕上打印: A N D R O I D字样。
    872     if( load_565rle_image(INIT_IMAGE_FILE) ) {
     873     fd = open("/dev/tty0", O_WRONLY);
     874     if (fd >= 0) {
     875         const char *msg;
     876             msg = "\n"
     877         "\n"
     878         "\n"
     879         "\n"
     880         "\n"
     881         "\n"
     882         "\n"  // console is 40 cols x 30 lines
     883         "\n"
     884         "\n"
     885         "\n"
     886         "\n"
     887         "\n"
     888         "\n"
     889         "\n"
     890         //"             A N D R O I D ";
     891         write(fd, msg, strlen(msg));
     892         close(fd);
     893     }
     894     }
     895
    # 触发在init脚本文件中名字为init的action,并且执行其commands,其实是:on init
    919     action_for_each_trigger("init", action_add_queue_tail);
     920     drain_action_queue();
    # 启动系统属性服务: system property service
    927     property_set_fd = start_property_service();

    # 创建socket用来处理孤儿进程信号
    930     if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
     931         signal_fd = s[0];
     932         signal_recv_fd = s[1];
     933         fcntl(s[0], F_SETFD, FD_CLOEXEC);
     934         fcntl(s[0], F_SETFL, O_NONBLOCK);
     935         fcntl(s[1], F_SETFD, FD_CLOEXEC);
     936         fcntl(s[1], F_SETFL, O_NONBLOCK);
     937     }

    # 触发在init脚本文件中名字为early-boot和boot的action,并且执行其commands,其实是:on early-boot和on boot
    948     action_for_each_trigger("early-boot", action_add_queue_tail);
     949     action_for_each_trigger("boot", action_add_queue_tail);
     950     drain_action_queue();
    # 启动所有属性变化触发命令,其实是: on property:ro.xx.xx=xx
    953     queue_all_property_triggers();
     954     drain_action_queue();
    # 进入死循环
    987     for(;;) {

    # 启动所有init脚本中声明的service,
    # 如:266 service servicemanager /system/bin/servicemanager
    #     user system
    #     critical
    #     onrestart restart zygote
    #     onrestart restart media

    994         restart_processes();
    # 多路监听设备管理,子进程运行状态,属性服务
    1012         nr = poll(ufds, fd_count, timeout);
    1013         if (nr <= 0)
    1014             continue;
    1016         if (ufds[2].revents == POLLIN) {
    1017             /* we got a SIGCHLD - reap and restart as needed */
    1018             read(signal_recv_fd, tmp, sizeof(tmp));
    1019             while (!wait_for_one_process(0))
    1020                 ;
    1021             continue;
    1022         }
    1023
    1024         if (ufds[0].revents == POLLIN)
    1025             handle_device_fd(device_fd);
    1026
    1027         if (ufds[1].revents == POLLIN)
    1028             handle_property_set_fd(property_set_fd);
    1029         if (ufds[3].revents == POLLIN)
    1030             handle_keychord(keychord_fd);
    1031     }
    1032
    1033     return 0;
    1034 }

     

    二、Android init脚本语言

    前面简单分析了下init.c里的操作,里面提到了解析Init.rc和硬件脚本下面详细解析下Android init脚本语言的规范。

    Android初始化语言包含了四种类型的声明:

        Actions(行为)、Commands(命令)、Services(服务)和Options(选项)

    • 所有这些都是以行为单位的,各种记号由空格来隔开。
    • C语言风格的反斜杠号可用于在记号间插入空格。
    • 双引号也可用于防止字符串被空格分割成多个记号。
    • 行末的反斜杠用于折行,注释行以井号(#)开头(允许以空格开头)。


    Actions和Services声明一个新的分组Section。所有的命令或选项都属于最近声明的分组。位于第一个分组之前的命令或选项将会被忽略。
    Actions和Services有唯一的名字。如果有重名的情况,第二个申明的将会被作为错误忽略。

    Actions(行为)
      Actions其实就是一序列的Commands(命令)。Actions都有一个trigger(触发器),它被用于决定action的执行时间。当一个符合action触发条件的事件发生时,action会被加入到执行队列的末尾,除非它已经在队列里了。
        队列中的每一个action都被依次提取出,而这个action中的每个command(命令)都将被依次执行。
    Actions的形式如下:
            on <trigger>
               <command1>
               <command2>
               <command3>
    on后面跟着一个触发器,当trigger被触发时,command1,command2,command3,会依次执行,直到下一个Action或下一个Service。
    简单来说,Actions就是Android在启动时定义的一个启动脚本,当条件满足时,会执行该脚本,脚本里都是一些命令commands,不同的脚本用on来区分。

    Triggers(触发器)
        Triggers(触发器)是一个用于匹配特定事件类型的字符串,用于使Actions发生。
            boot:
                这是init执行后的第一个被触发的Triggers(触发器)。(在 /init.conf (启动配置文件)被装载之后)
            <name>=<value>:
                这种形式的Triggers(触发器)会在属性<name>被设置为指定的<value>时被触发。
            device-added-<path>:
            device-removed-<path>:
                这种形式的Triggers(触发器)会在一个设备节点文件被增删时触发。
            service-exited-<name>:
                这种形式的Triggers(触发器)会在一个特定的服务退出时触发。
    触发器通常和on一起来联合使用。
    示例:
    on init
      export LD_LIBRARY_PATH /system/lib
      insmod modules/fsr.ko
      symlink /system/etc /etc
      mkdir /sdcard 0000 system system
      write /proc/cpu/alignment 4

    on boot
      …
    on property:ro.kernel.qemu=1
       start adbd
    上面声明了三个action:init,boot和一个属性触发器,当init被触发时,会顺序执行后面的命令,直到on boot新的action。Init的触发是由init.c里的函数action_for_each_trigger来决定的。当属性ro.kernel.qemu为1 时,会触发start adbd命令。


    Services(服务)
    Services(服务)是一个程序,它在初始化时启动,并在退出时可选择让其重启。Services(服务)的形式如下:
            service <name> <pathname> [ <argument> ]*
               <option>
               <option>
               ...
    name:服务名
    pathname:当前服务对应的程序位置
    option:当前服务设置的选项

    Options(选项)
        Options(选项)是一个Services(服务)的修正者。他们影响Services(服务)在何时,并以何种方式运行。
         critical:
                说明这是一个对于设备关键的服务。如果他四分钟内退出大于四次,系统将会重启并进入recovery(恢复)模式。

         disabled:
                说明这个服务不会同与他同trigger(触发器)下的服务自动启动。他必须被明确的按名启动。

         setenv <name> <value> (设置环境变量)
                在进程启动时将环境变量<name>设置为<value>。

         socket <name> <type> <perm> [ <user> [ <group> ] ]
                创建一个Uinx域的名为/dev/socket/<name> 的套接字,并传递它的文件描述符给已启动的进程。<type> 必须是 "dgram"或"stream"。User 和 group默认为0。

         user <username>
                在启动这个服务前改变该服务的用户名。此时默认为root。(???有可能的话应该默认为nobody)。当前,如果你的进程要求Linux capabilities(能力),你无法使用这个命令。即使你是root,你也必须在程序中请求capabilities(能力)。然后降到你想要的 uid。

         group <groupname> [ <groupname> ]*
                在启动这个服务前改变该服务的组名。除了(必需的)第一个组名,附加的组名通常被用于设置进程的补充组(通过setgroups())。此时默认为root。(???有可能的话应该默认为nobody)。
       
         oneshot
                服务退出时不重启。

         class <name>
                指定一个服务类。所有同一类的服务可以同时启动和停止。如果不通过class选项指定一个类,则默认为"default"类服务。

         onrestart
                当服务重启,执行一个命令(下详)。

    Commands(命令)
        exec <path> [ <argument> ]*
             创建和执行一个程序(<path>)。在程序完全执行前,init将会阻塞。由于它不是内置命令,应尽量避免使用exec,它可能会引起init卡死。(??? 是否需要一个超时设置?)
        export <name> <value>
            在全局环境变量中设在环境变量 <name>为<value>。(这将会被所有在这命令之后运行的进程所继承)
        ifup <interface>
            启动网络接口<interface>
        import <filename>
               解析一个init配置文件,扩展当前配置。
        hostname <name>
               设置主机名。
        chmod <octal-mode> <path>
               更改文件访问权限。
        chown <owner> <group> <path>
               更改文件的所有者和组。
        class_start <serviceclass>
               启动所有指定服务类下的未运行服务。
        class_stop <serviceclass>
            停止指定服务类下的所有已运行的服务。
        domainname <name>
               设置域名。
        insmod <path>
               加载<path>中的模块。
        mkdir <path> [mode] [owner] [group]
               创建一个目录<path>,可以选择性地指定mode、owner以及group。如果没有指定,默认的权限为755,并属于root用户和root组。
        mount <type> <device> <dir> [ <mountoption> ]*
            试图在目录<dir>挂载指定的设备。<device> 可以是以 mtd@name 的形式指定一个mtd块设备。<mountoption>包括 "ro"、"rw"、"remount"、"noatime"、 ...
        setprop <name> <value>
               设置系统属性 <name> 为 <value>值.
        setrlimit <resource> <cur> <max>
            设置<resource>的rlimit(资源限制)。
        start <service>
            启动指定服务(如果此服务还未运行)。
        stop <service>
            停止指定服务(如果此服务在运行中)。
        symlink <target> <path>
            创建一个指向<path>的软连接<target>。
        sysclktz <mins_west_of_gmt>
            设置系统时钟基准(0代表时钟滴答以格林威治平均时(GMT)为准)
        trigger <event>
               触发一个事件。用于将一个action与另一个 action排列。
        write <path> <string> [ <string> ]*
               打开路径为<path>的一个文件,并写入一个或多个字符串。

    Properties(属性)
        Init更新一些系统属性以提供对正在发生的事件的监控能力:
            init.action
                   此属性值为正在被执行的action的名字,如果没有则为""。
            init.command
                   此属性值为正在被执行的command的名字,如果没有则为""。
            init.svc.<name>
                   名为<name>的service的状态("stopped"(停止), "running"(运行), "restarting"(重启))

     

    三、Android init 示例

      1 on init
      2
      3 sysclktz 0
      4
      5 loglevel 3
      6
      7 # setup the global environment
      8     export PATH /system/busybox/bin:/system/busybox/sbin:/system/busybox/usr/bin:/system/busybox/usr/sbin:/sbin:/system/sbin:/system/bin:/system/xbin
      9     export LD_LIBRARY_PATH /system/lib
     10     export ANDROID_BOOTLOGO 1
     11     export ANDROID_ROOT /system
     12     export ANDROID_ASSETS /system/app
     13     export ANDROID_DATA /data
     14     export EXTERNAL_STORAGE /sdcard

    ... ...

     23     symlink /system/etc /etc
     24     symlink /sys/kernel/debug /d
     25    
     26 # create mountpoints and mount tmpfs on sqlite_stmt_journals
     27     mkdir /sdcard 0000 system system
     28     mkdir /system
     29     mkdir /data 0771 system system
     30     mkdir /cache 0770 system cache
     31     mkdir /config 0500 root root
     32     mkdir /sqlite_stmt_journals 01777 root root
     33     mount tmpfs tmpfs /sqlite_stmt_journals size=4m
     34
     35 #    mount rootfs rootfs / ro remount
     36
     37     write /proc/sys/kernel/panic_on_oops 1
     38     write /proc/sys/kernel/hung_task_timeout_secs 0
     39     write /proc/cpu/alignment 4
     40     write /proc/sys/kernel/sched_latency_ns 10000000
     41     write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
     42     write /proc/sys/kernel/sched_compat_yield 1
     43     write /proc/sys/kernel/sched_child_runs_first 0
     44
     45 # Create cgroup mount points for process groups
     46     mkdir /dev/cpuctl

     47     mount cgroup none /dev/cpuctl cpu
     48     chown system system /dev/cpuctl
     49     chown system system /dev/cpuctl/tasks
     50     chmod 0777 /dev/cpuctl/tasks
     51     write /dev/cpuctl/cpu.shares 1024
     52
     53     mkdir /dev/cpuctl/fg_boost
     54     chown system system /dev/cpuctl/fg_boost/tasks
     55     chmod 0777 /dev/cpuctl/fg_boost/tasks
     56     write /dev/cpuctl/fg_boost/cpu.shares 1024
     57
     58     mkdir /dev/cpuctl/bg_non_interactive
     59     chown system system /dev/cpuctl/bg_non_interactive/tasks
     60     chmod 0777 /dev/cpuctl/bg_non_interactive/tasks
     61     # 5.0 %
     62     write /dev/cpuctl/bg_non_interactive/cpu.shares 52
     ... ...

    146 on boot
    147 # basic network init
    148     ifup lo
    149     hostname localhost
    150     domainname localdomain
    151
    152 # set RLIMIT_NICE to allow priorities from 19 to -20
    153     setrlimit 13 40 40
    154
    155 # Define the oom_adj values for the classes of processes that can be
    156 # killed by the kernel.  These are used in ActivityManagerService.
    157     setprop ro.FOREGROUND_APP_ADJ 0
    158     setprop ro.VISIBLE_APP_ADJ 1
    159     setprop ro.SECONDARY_SERVER_ADJ 2
    160     setprop ro.BACKUP_APP_ADJ 2
    161     setprop ro.HOME_APP_ADJ 4
    162     setprop ro.HIDDEN_APP_MIN_ADJ 7

    ... ...

    233 # Define TCP buffer sizes for various networks
    234 #   ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax,
    235     setprop net.tcp.buffersize.default 4096,87380,110208,4096,16384,110208
    236     setprop net.tcp.buffersize.wifi    4095,87380,110208,4096,16384,110208
    237     setprop net.tcp.buffersize.umts    4094,87380,110208,4096,16384,110208
    238     setprop net.tcp.buffersize.edge    4093,26280,35040,4096,16384,35040
    239     setprop net.tcp.buffersize.gprs    4092,8760,11680,4096,8760,11680
    240     setprop net.dns1 8.8.8.8
    241     setprop net.eth0.dns1 8.8.8.8
    242
    243     class_start default

    ... ...

    247 service console /system/bin/sh
    248    console
    249

    252 service adbd /sbin/adbd
    253     disabled'

    259 on property:persist.service.adb.enable=1
    260     start adbd
    261
    262 on property:persist.service.adb.enable=0
    263     stop adbd

    265 service servicemanager /system/bin/servicemanager
    266     user system
    267     critical
    268     onrestart restart zygote
    269     onrestart restart media

    271 service vold /system/bin/vold
    272     socket vold stream 0660 root mount

     

    282 service ril-daemon /system/bin/rild
    283     socket rild stream 660 root radio
    284     socket rild-debug stream 660 radio system
    285     user root
    286     group radio cache inet misc
    287
    288 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    289     socket zygote stream 666
    290     onrestart write /sys/android_power/request_state wake
    291     onrestart write /sys/power/state on
    292     onrestart restart media

    293
    294 service media /system/bin/mediaserver
    295     user media
    296     group system audio camera graphics inet net_bt net_bt_admin
    297
    298 service bootsound /system/bin/playmp3
    299     user media
    300     group audio
    301     oneshot
    302
    303 service bootanim /system/bin/bootanimation
    304     user graphics
    305     group graphics

    306     disabled
    307     oneshot

    ... ...

    由上面的例子可知:该init.rc里定义了4个actions:

        on init

        on boot

        on property:persist.service.adb.enable=1
        on property:persist.service.adb.enable=0
       其中,前两个的触发器是由Init.c里的代码action_for_each_trigger实现触发的,后两个是由属性的值发生改变时触发的。当他们被触发时,会依次执行其后面的值,直到遇到一个新的Action或service。

    该init.rc中定义了9个services,这些service属于本地服务,它们都是由c或c++代码写的,以可执行文件的方式存在文件系统里的/system/bin或/sbin目录下。由前面知识可知,如果一个服务没有使用class选项指定其分类,则其默认分类为:default,那么这9个services的分类为default。在on boot action触发时,其最后一个命令是class_start default,也就是将这9个services都依次启动。

    init.rc中的9个service里,以zygote和servicemanager最为重要。

    1> zygote service

    该service主要用于创建Dalvik Java虚拟机,然后启动SystemServer,启动所有的Android服务,最终启动Android系统。

    2> servicemanager

    该service主要用来打开binder驱动,binder是Android Service通信机制的底层实现,在该service里封装了binder的操作接口。

    技巧:

      在调试或理解系统的工作原理的时候,我们经常要去找服务程序对应的源码。

      寻找c或c++程序的源码文件:

      例如:以寻找init程序对应的源码为例。

       find ./ -name Android.mk -exec grep -l init {} \;

      注:通过find命令查找所有的Android.mk, 通过grep从中查找程序字符串,得到其路径,然后去路径下找源码即可,这么做的原因是,c或c++代码都是通过Android.mk来指导编译的。

       寻找java源码文件:

       java源码的特点是和类名一致,所以如果我们知道一个类名,找其java源码就直接加上java后缀即可。

      例如:寻找com.android.internal.os.ZygoteInit类的代码。

       find ./ -name ZygoteInit.java

    展开全文
  • 进程之init进程

    2019-01-11 13:51:25
    进程 进程是Linux内核最基本的抽象之一,它是处于执行期的程序,或者说“进程=程序+执行”。但是进程并不仅局限于一段可执行代码(代码段),它还包括进程需要的其他资源,例如打开的文件、挂起的信号量、内存管理...
  • Android7.0 init进程源码分析

    万次阅读 多人点赞 2016-08-07 20:07:26
    主要对Android 7.0中,init进程的源码进行分析。
  • 原文地址:... Android系统启动流程 Android系统启动过程往细了说可以分为5步: Loader --》Kernel --》Native --》Framework --》Application Loader ...Boot ROM: 当手机处于关机状态时,长按Power键...
  • Init进程和进程 ④

    2014-08-17 11:16:45
    1、Init进程:是用户空间的初始化进程,是用户空间启动的第一个进程。用户空间的其他所有进程都由init来管理,无需内核管理。2、进程:是程序的实例,进程有生命周期。备注:程序成为进程的过程:向内核申请内存空间...
  • Linux将要建立的第一个进程是init进程,建立该进程是以调用kernel_thread(init ,NULL,0)这个函数的形式进行的。init进程是很特殊的——它是Linux的第一个进程,也是其它所有进程的父进程。让我们来看一下它是...
  • init进程与zygote进程

    2017-11-06 11:33:41
    如图,通过ps命令看到的init进程和守护进程之间的关系。 zygote进程生成系统服务器端和各种java应用程序进程。 init进程在所有系统中通常具有固定的pid值(pid=1),但启动其他进程时,不同系统赋予的pid值也有所...
  • 进程0 :  所有进程的祖先叫做进程0 ,idle 进程或因为历史的原因叫做swapper 进程。它是在 linux 的初始化阶段从无到有的创建的一个内核线程。这个祖先进程使用静态分配的数据结构。 在多处理器系统中,每个CPU...
  • Init 进程详解

    千次阅读 2017-11-13 11:16:13
    Android 内核加载完成后,就会启动init进程,init进程是Android系统用户空间的第一个进程。init程序放在系统根目录下,init进程代码位于源码的目录“system/core/init”下面。下面我们来分析init进程的启动过程1. ...
  • linux init进程

    千次阅读 2016-09-11 12:36:08
    linux init进程

空空如也

1 2 3 4 5 ... 20
收藏数 12,653
精华内容 5,061
关键字:

init进程