Basic Process of android init process analysis

Source: Internet
Author: User

Basic Process of android init process analysis

(The lazy recently remembered that I still have csdn for a long time and I haven't taken care of it. This android init has been lying in my draft box for almost five years. Let's change it a little)

When the android device is powered on, the boot program directs to boot (usually uboot), loads the initramfs and kernel images, starts the kernel, and enters the user State program. The first user space program is init, And the PID is fixed to 1. On the android system, the init code is located in/system/core/init. The basic functions are as follows:

Manage device resolution and process STARTUP script init. rc to maintain services in init. rc in real time

System initialization and service process of the init process. You can simply look at the main function in init. c. Here, we will briefly analyze the main functions of this function. The details will not be expanded or will be expanded later.

Briefly describe the operations of the main function:

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

The above section is the first sentence of the main function entry. This is the program to be run.

/System/core/init: The compiled binary executable program init is actually divided into three programs, which indicates that you can share a piece of code. The three parts are:
/Init: the actual init executable program
/Sbin/ueventd: ueventd daemon program, which is the soft link of init
/Sbin/watchdogd: watchdogd daemon program, which is also the soft link of init.

As we all know, the first of the main function parameter argv, argv [0] is its own running directory path and program name. Here we will judge the path of the code based on this condition. Why? In fact, you can write another ueventd or watchdogd program to define the main function. In fact, the reason is also very simple. They share too many things and simply write them together! Just like how busybox or toolbox integrates so many command tools.

    /* clear the umask */    umask(0);

Clear umask. This is mainly about file permissions. With umask, you can remove some file permissions from the global mask.

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

Linux requires the loading of dev, proc, sys and other file systems.

 

        /* indicate that booting is in progress to background fw loaders, etc */    close(open(/dev/.booting, O_WRONLY | O_CREAT, 0000));

 

 

 

 

 

 

Create a/dev/. booting file. /Dev is a memory file system and won't be saved. It needs to be re-created every time it is started. This is an indication of how to use ueventd during the booting process. It is used to load the fimware of the device.

    open_devnull_stdio();    klog_init();    property_init();

The three statements initialize stdin, stdout, and stderr to/dev/_ null __. in this way, no output can be made using printf or other printed statements, it will not cause other exceptions (in this phase, it is not actually usable and will cause errors ).

Note that this/dev/_ null _ is a temporary name. It is deleted after the node is created and does not affect the true/dev/null system. Here, you only need fd, with fd, the file name will be useless and there will be interference.

Klog_init is a method used to print logs in the init process to the log buffer of the kernel printk. This is very helpful for debugging init. After all, there is no shell at this time. General log output methods, such as printf, cannot work yet. Of course, it is the best to use the underlying kernel debugging function.

Property Initialization is also here. property Reading can be performed in various user processes, but the setting entry must be in the init process. In 4.4, the property field has been modified a lot. Now it is stored in the dictionary tree and supports more property attributes.

 get_hardware_name(hardware, &revision);

Read the hardware information from/proc/cpuinfo and set it to the ro. hardware attribute to facilitate later parsing of init. $ {ro. hardware}. rc.

    process_kernel_cmdline();

The command parameter of the kernel is resolved and placed in the property for later use by sub-processes or other services.

    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);    selinux_initialize();    /* 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__);    restorecon_recursive(/sys);

Selinux initialization and check. If selinux is not carefully studied, the check process is sometimes quite time-consuming.

    INFO(property init);    if (!is_charger)        property_load_boot_defaults();

This is to load and set properties. These are pre-configured properties, which are usually pre-configured in the/system/build. prop and default. prop files.

init_parse_config_file(/init.rc);

This is the beginning of parsing the init. rc file. The details and the format and writing of init. rc are everywhere on the Internet. The following are some common problems:
1. on the server where the code is downloaded, umask may sometimes be affected. The other and group users in the init. rc file do not have the write permission. The compiled PC umask should be set to 0022.
2. The init. rc file is strictly a configuration file, not a script, loop, condition judgment, and so on. Do not think that too many things can be done here.

    action_for_each_trigger(early-init, action_add_queue_tail);    queue_builtin_action(wait_for_coldboot_done_action, wait_for_coldboot_done);    queue_builtin_action(mix_hwrng_into_linux_rng_action, mix_hwrng_into_linux_rng);    queue_builtin_action(keychord_init_action, keychord_init);    queue_builtin_action(console_init_action, console_init);    /* execute all the boot actions to get us started */    action_for_each_trigger(init, action_add_queue_tail);    ...

This is the various commands that start to process parser in init. rc.

Action_for_each_trigger is used to add all the commands where the trigger belongs to the actions list. Take a global look at the actual code or project. All the *. rc triggers are processed together.

Queue_builtin_action: This is the built-in actions and adds the actions action to the actions list.

Note that the loading sequence of each trigger is first executed, and then executed after the trigger is added. In particular, you must modify the init. when the rc file is used, it is easy to understand that this problem is caused by the front-end dependency.

 

If everything is ready, it is the service processing stage. This is an endless loop and the main task is:
1. run init. rc and the built-in actions command one by one.
2. Manages services.
3. Processing of signal and process exit
4. Respond to the requests set by property (the settings are all set in init, And the read process can read the shared memory by itself)

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

If you need to optimize the startup, you can measure the command execution time in execute_on_command, print out a long period (for example, more than 50 ms), and try to optimize it.

Execute a command every cycle to check whether there are services to be restarted ..

        nr = poll(ufds, fd_count, timeout);        if (nr <= 0)            continue;        for (i = 0; i < fd_count; i++) {            if (ufds[i].revents == POLLIN) {                if (ufds[i].fd == get_property_set_fd())                    handle_property_set_fd();                else if (ufds[i].fd == get_keychord_fd())                    handle_keychord();                else if (ufds[i].fd == get_signal_fd())                    handle_signal();            }        }

Multi-channel polling, when polling arrives at something, it will execute the corresponding action.

The timeout time is up, and the next cycle is executed. If the command in init. rc is not completed, the timeout value is 0, so that the previous actions list can be executed smoothly.
Note that the service defined in init. rc is implemented in the class_start command.

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.