Friday, August 28, 2009

The init process and init.rc

In this post I will wrap up the analysis of what is going on at boot by looking at the Android init process and the init.rc file. If we start with the source you will find the code for the init process under /system/core/init in the source tree. The init process is what will set up all native services and this is similar to a regular Linux system boot. At this stage we are not executing in the actual android runtime. There is however some Android specifics going on already at this level. One example of this is that the init.rc script is written in a specific format called the Android init language. This is covered in the readme file that is kept in the same directory as the init source. Since I have not seen very much about it on the net though I will post some of the main concepts here. I will also give a small example on how to add your own native service at startup.

The Android init language
The language used by the init process has four classes of statements. These are actions, commands, services and options. Actions are associated to commands in the way that an action is a sequence of commands. An action also need something called a trigger in that the sequence of commands will be executed when the trigger event has occured. An exemple may look like:
on boot
ifup lo
hostname localhost
domainname localdomain
This action will run a command sequence to set up basic networking once it receives the boot trigger. The supported commands include export, chmod, chown and a few others. The complete list of available commands can be found in the readme file.
Services are programs that are launched by init. They are associated with options which control how they are started. The syntax for starting a service is:
service < name > < pathname > [< argument > ]*
< option >
< option >
...
There is a number of options available and a few of them are:
critical - this is a critical process and init will restart the device if it exists more than four times in four minutes
user < username > - change to this username before executing the service
group < groupname > [< groupname > ]* - change to groupname before executing the service
setenv < name > < value > - set environment variable < name > to < value > in the launched process
The init script is also the place where some important system properties are set. This is done with the setprop command and include things like the memory thresholds for applications, tcp buffer sizes etc.
The init.rc file itself is found in the root directory on a device and in the source tree it is kept under system/core/rootfs. The below example is the actual init.rc file that I have shortened significantly. The basic concepts are clearly illustrated. First there is an action on init where a long sequence of commands is run. As you can see it is accepted to use comments and they are preceded by #. A number of variables are setup during init and file systems are mounted. The next step is the boot action where networking is set up and properties assigned to the system. Then there is a list of services to be started by init.
on init
sysclktz 0
loglevel 3
# setup the global environment
export PATH /sbin:/system/sbin:/system/bin:/system/xbin
export LD_LIBRARY_PATH /system/lib
export ANDROID_BOOTLOGO 1
export ANDROID_ROOT /system
...
# mount mtd partitions
1. 
Mount /system rw first to give the filesystem a chance to save a checkpoint
mount yaffs2 mtd@system /system
mount yaffs2 mtd@system /system ro remount
2. 
We chown/chmod /data again so because mount is run as root + defaults
mount yaffs2 mtd@userdata /data nosuid nodev
chown system system /data
chmod 0771 /data
...
on boot
# basic network init
ifup lo
hostname localhost
domainname localdomain
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit 13 40 40
# Define the oom_adj values for the classes of processes that can be
# killed by the kernel. These are used in ActivityManagerService.
setprop ro.FOREGROUND_APP_ADJ 0
setprop ro.VISIBLE_APP_ADJ 1
setprop ro.SECONDARY_SERVER_ADJ 2
setprop ro.BACKUP_APP_ADJ 2
setprop ro.HOME_APP_ADJ 4
setprop ro.HIDDEN_APP_MIN_ADJ 7
setprop ro.CONTENT_PROVIDER_ADJ 14
setprop ro.EMPTY_APP_ADJ 15
...
## Daemon processes to be run by init.
##
service console /system/bin/sh
console
# adbd is controlled by the persist.service.adb.enable system property
service adbd /sbin/adbd
disabled

Starting your own service at boot.
Normally there is not much need to do things in the init script and start services of your own. What is provided in the system goes a long way and often it may be better to add something to the Android runtime instead of using the native services. If you have a reason to add something or just what to try things out however it is relatively straight forward to add a native service to that init sequence. I have created a simple example that writes the time elapsed since it started to the log. It wakes up every three seconds. The code for exampleservice.c looks like:
#define LOG_TAG "Example Service"
#include < utils/log.h >
#include < unistd.h >
int main(int argc, char **argv)
{
    LOGI("Service started");
    int elapsed = 0;
    while(1)
    {
         sleep(3);
         elapsed += 3;
         LOGI("Service elapsed time is %d", elapsed);
    }
}
Place this somewhere in the platform build system and build as an executable. The build system will place the output in the /system/bin folder on the device. Now all that is needed is to add the following to the init.rc script:
service exampleservice /system/bin/exampleservice
user exampleservice
group exampleservice
oneshot
and your service will start on init. It is also possible to write your own file using the Android init language that enables your services and variables. Then just add a line to import the file in init.rc and you are done.
/Mattias

44 comments:

  1. hi, can you explain more about "Place this somewhere in the platform build system and build as an executable."
    is there any special way to build c/c++ program for Android by using the "android build system"?
    thanks

    ReplyDelete
  2. If you are using the Android Open Source Project (aosp) there are some make file templates and a toolchain available to build Android for Arm. The easiest way to test the above is to add the example code somewhere in the aosp codebase (e.g. /development or /vendor) and add an Android.mk file as described in the build system posts.

    Another way to do it is to compile the example program with the correct toolchain (arm for the emulator) and copy the executable file to the system image.

    ReplyDelete
  3. Thanks for the reply. and I found the old post about the Andoid build system, it helps.

    ReplyDelete
  4. 2. make a folder ANDROID/external/myservice
    3. create your cpp files.
    4. create Android.mk as clon of /ping/Android.mk
    6. Change the names ping.c and ping to match your cpp files and service name
    7. add the folder name in ANDROID/build/core/main.mk
    after external/zlib as external/myservice
    8. make from AND_ROOT

    ReplyDelete
  5. I am trying to start tcpdump(as described in http://pdk.android.com) at boot, by kicking it of in init.rc, but without success. Any suggestions?

    ReplyDelete
  6. I am facing the same problem while starting ping application!! The funny thing is my changes to init.rc are not reflected after I do "adb pull" and "adb push"!! Any comments please?

    ReplyDelete
  7. The init.rc script is parsed by the init process at boot. This means that a uploading a new script after boot will not have an effect until the system is restarted. To test changes to init.rc in the emulator make sure that you have an updated init.rc in the system image and restart the emulator.

    ReplyDelete
  8. How to include a own init script in the init.rc?

    ReplyDelete
  9. hii..
    I am trying to run my own script through init.rc
    say i have an script file test.sh which contains some simple code to display some text. I want to execute it through init.rc while booting the system. Please help me how i can add this in the init.rc file.

    thanks
    AN

    ReplyDelete
  10. Apologize for not addressing this question until now. To run your own script as part of init you need to create the script and make sure it is available on the target. Let us say we create a script called myscript.sh like

    #!/system/bin/sh
    echo Running my setup script

    and put it in system/etc/ on the device. Then just add the following to the init.rc script to run it:

    #my init testscript
    service myscript /system/etc/myscript.sh
    oneshot

    ReplyDelete
  11. Hi,

    This is vinay , I need to develope a factory test software to test the functionality of the phone devices at the factory before releasing into the market. For this requirement need to give an option to tester to select factory mode or normal mode . Now i am unable to decide what is the right place for this option Whether at uboot prompt or before Android file system work on Kernal , Please help me on the same if anybody Know .

    Thanks
    Vinay

    ReplyDelete
  12. Hi there!

    Is there anywhere a syntax description available for the syntax of the init.rc file. Especially interesting for me is the syntax of mount, because I would like to mount a file system different to yaffs2 (ubifs).
    Thank you very much
    Günther

    ReplyDelete
  13. Hi Günther,
    There is a description of the init language available in a readme file in the platform source. You will find it under /system/core/init/readme.txt in the platform distribution (or here: https://android.git.kernel.org/?p=platform/system/core.git;a=blob;f=init/readme.txt;h=a185790acb05904ddd109ed33de3863a4b413d53;hb=HEAD)

    For mount the description is as follows:
    mount <type> <device> <dir> [ <mountoption> ]*
    Attempt to mount the named device at the directory <dir>
    <device> may be of the form mtd@name to specify a mtd block
    device by name.
    <mountoption>s include "ro", "rw", "remount", "noatime", ...

    ReplyDelete
  14. I placed a trigger after the on boot section to detect a device class file
    on device-added-/sys/class/virtual/....
    chown ..
    chmod ...

    I checked the file (node) is created, but the chmod and chown weren't executed.

    It doesn't seem to trigger this. Any suggestion on how shall I debug this?

    Thanks,

    ReplyDelete
  15. Hi ur blog is very usefull thanks.......
    I am trying to load someother app or some screen instead of the default home screen after boot......

    I know this could be easily done with "broadcast receivers" and all..... I just wanted to play with kernel i could say...

    so if any suggestions plz respond ..... :)
    Thanks in advance and Thanks for ur blog input :)

    ReplyDelete
  16. Hello,

    I have a query regarding the init.rc.

    There is generally an entry for bluetooth

    service hciattach /system/bin/logwrapper /system/bin/hciattach -n -s 115200 /dev/ttyAMA0 any 115200 flow
    user bluetooth
    group bluetooth net_bt_admin
    disabled
    oneshot

    I want to know, since we have written the disabled keyword, it means the service would not be started, on boot time, so how is the service started ?

    ReplyDelete
  17. Hi,
    Regarding the disabled keyword it means as you say that the service is not started on boot time. This is the case for some bluetooth related services and a few more. What this means is that the service must be explicitly started later. In this case by doing a call to property set

    property_set("ctl.start", "hciattach")

    This will trigger a property change in the init process and an action to start the service will be queued and executed. In the same way the service is stopped when bluetooth is disabled with a similar call

    property_set("ctl.stop", "hciattach")

    The reason for this is probably to avoid having the bluetooth services running when bluetooth is not used.

    property_set is available in the android system and is handled by the property_service in the init process.

    /Mattias

    ReplyDelete
  18. Hi Mattias,
    Suppose we have two .rc files one for the hardware and other general init.rc . Both of the files have triggers at a common event. In this case which actions would take precedence ?
    thanks,
    Dhiraj

    ReplyDelete
  19. Hi Mattias,
    Is there a way to specify the init process to pick a product customized init.rc instead of the default init.rc present @ system/core/rootdir

    Many Thanks
    Suri

    ReplyDelete
  20. Hi Suri,
    Yes, there is a way to pick a customized init.rc file for your product. But reg which module is responsible to pick it based on some condition , am not sure.
    Regards, Robin.

    ReplyDelete
  21. is there a way to
    export VARIABLE value
    conditionally in init.rc?

    we need to export to value1 or value2, or to read the value from file. is it possible?

    ReplyDelete
  22. Is there any way to give priority to the service from init.rc ?

    ReplyDelete
  23. Hello:

    I want to copy a file to the sdcard during the init process. It seems the sdcard is mounted by the vold service.

    I was thinking on a script, which would be run by a service, which needs to be started once the vold service mounts the sdcard. Is there a way to check that vold service has finished mounting the sdcard?

    Thanks in advanced!

    ReplyDelete
  24. Hello:

    This is how I solved the problem. I added this in init.rc:

    service myfile_sd /system/bin/sh /system/etc/init.streak.myfile_sd.sh
    disabled
    oneshot

    on property:persist.sys.sdcard.enable=1
    start myfile_sd

    and just to be on sync, in myfile_sd.sh I needed to include a sleep at the beginning, to let the sdcard be completely mounted before copying the file.

    Hope this helps someone.

    ReplyDelete
    Replies
    1. Hi Jose,
      Thanks for your post. It helps to copy file to SD card in bootup.
      Can we display a progress bar or some kind of animation while this is being done at boot up? Any idea how could i achieve this ? any animation utility available ?
      Thanks in advance.

      vijaykumar.nc@gmail.com

      Delete
  25. Hi,

    I have 1 java service, which starts at boot time by reciving android.intent.action.BOOT_COMPLETED intent.

    but i want to change the owner and grop of my running service, so that i can get access to /cache folder. /cache permission are drwxrwx---.
    Can i start java service from init.rc ?
    How we can change user or group of runing service?

    Thanks in Advance............

    ReplyDelete
  26. Hi Mattias,

    Your blogs are good. really helpful for beginners.
    How to play a mp3 file at the boot time?
    What is major difference between init.rc & init..rc
    Thanks

    ReplyDelete
  27. Hi Mathias,

    Nice blog. lot of info :)
    Btw I was trying to write a simple script as startup and followed these steps but I dont see it working :(
    1)Wrote a script hello.sh that says "hello" all the time in the background(like daemon)
    2)Placed it in the out/target/product/generic/system/etc/hello.sh
    3)Modified my init.rc also in out/target/product/root/core/init.rc
    4)simply rebooted it- with no effect.
    5)So did a "make" on my sources
    6) With adb shell commands: I do see my script in /system/etc and also the changed init.rc the script doesnt run :(

    What is wrong?

    ReplyDelete
  28. Hi Mathias,

    Great post.

    I have a question. I was able to start a service
    with the following

    service rtsp_server /system/bin/rtsp_server
    user rtsp_server
    group rtsp_server

    It works without any problem. What I would like to do is able to stop and start this service from an app. For eg), issuing from command line prompt,
    "setprop ctl.stop rtsp_server" works.. However, if I try that from an app, I guess I am running into the same 'privilege' problem as it complains like this,

    "init: sys_prop: Unable to stop service ctl [rtsp_server] uid: 10038 pid:22575"

    So, what do you suggest? Is there way to run privileged commands from an app or is it possible to make the service accessible to normal user?

    Thanks,
    Krishnan.

    ReplyDelete
  29. Hello,
    Thanks for the good document,\.
    I have a query:I want to have some splash images at the time of booting process before bootanimation how to i do it in init.rc

    ReplyDelete
  30. Shilpa, the simple answer is that you don't. You can have a splash image in the bootloader and then replace that with bootanimation. If you need more than two splash screens you may of course add them in init.rc similar to bootanimation or you can extend the bootanimation itself to show as many splash screens as you like, but surely two splash screens are enough?

    ReplyDelete
  31. I'd like to execute commands in an early stage of init which are stored in the initrd.gz file. But it fails.
    When does the initrd precisely being freed out of memory?
    Thx

    ReplyDelete
  32. Hi guys, I'm wondering.

    Is there a way to change the rootfs mount points by either:

    1. Replacing init with a script
    2. Using init.rc?

    The reason being, on my new tablet I want the kernel to look for the rootfs on the SDCard rather than the internal flash memory, providing I know the mount points, what's the best way to do it?

    ReplyDelete
  33. Hello and thanks and compliments for the article.

    I found this while researching on how to boot alternative operating systems to android in a HTC device.

    Do you think that just by modifying the init.rc script, a debian, ubuntu... port could be loaded instead of android?

    Thanks, again.

    ReplyDelete
  34. Hello and thanks and compliments for this article.

    I'd like to know if by modifying the init.rc script, alternate operating systems like debian or ubuntu could be loaded instead of android, having in mind that they have been properly ported.

    Also, is here where it could be implemented a multiboot system?

    Thanks, again.

    ReplyDelete
  35. Hi Mathias,
    Great post, years past this post and the article is still green and live.

    In init.rc file there are instructions like
    class_start abcd
    class_start xyz

    I want to figure out what these classes are and where is the code for these classes - where can I locate them - probably in some manifest or some xml or so on. I checked in /system/bin and could not find a executable named abcd or xyz. I am not sure where the service's exectuable are present either.

    Additionally, what does the below statement mean, what is "default" & "main", as this appears to be standard in most init.rc file.
    class_start default
    class_start main.

    Thanks.

    ReplyDelete
  36. Hi,

    I am running a Server as service that parses data from a client application and executes recording or playback from the ADCs and DACs on the board.
    I execute ps command and find the the application running as service but when I give the command to run the application it initiates the record but no recording happens. However when the same application is run not as a service but manually it seems to record the data perfectly.

    Does running an application alter the behaviour of the application?

    Thanks,
    Milind

    ReplyDelete
  37. Sorry, A correction.
    Does running an application as a service alter the behaviour in some manner.

    ReplyDelete
  38. Hello,

    I am currenly using a imx6 real board and trying to build android on it.
    But facing some problem running the init program. I have flashed the ramdisk.img in to the micro sd card. board boots up from micro sd. it reaches till "Freeing init memory 212K"
    after that nothing....

    Please help us

    ReplyDelete
  39. where are located the data used to know which process has to be reloaded

    ReplyDelete
  40. Very useful discussion:
    Does the init.rc script parsed sequentially? for example, in the init.rc script, starting of the servicemanager is before the starting of the media service. Does this guarantee starting of servicemanager prior to the media service?

    ReplyDelete
  41. hi i have a query..
    suppose i want to start service "x" in init.rc only if the service binary exists in /system/bin/"x"..
    what condition can be added in init.rc to "start x"..

    ReplyDelete
  42. What is the scope of "on" triggers? Are they valid only during the execution of init or do they remain beyond the boot process?

    ReplyDelete