Android Startup Process [zz]

Source: Internet
Author: User

This article mainly introduces the Linux kernel startup process and the process of mounting the android root file system, as well as the analysis of the file system in the android source code.

1. Introduction to the main source code directory
Makefile (Global makefile)
Bionic)
Bootable)
Build (the content in the build directory is not the code used by the target, but the scripts and tools required for compilation and configuration)
Dalvik (Java Virtual Machine)
Development (templates and tools required for Program Development)
External (some libraries used by the target machine)
Frameworks (framework layer of the Application)
Hardware (hardware-related database)
Packages (various Android applications)
Prebuilt (preset scripts compiled by android on various platforms)
Recovery (related to the recovery function of the target)
System (some underlying libraries of Android)
Out (the directory generated after compilation, that is, the directory required for porting the file system)

The structure of the host directory is as follows:
Out/host/
| -- Common
| '-- OBJ (Java Library)
'-- Linux-x86
| -- Bin (Binary Program)
| -- Framework (Java library, *. jar file)
| -- Lib (shared library *. So)
'-- OBJ (the target file generated in the middle)
The host directory is a tool used on the host. Some are binary programs and some are Java programs.

The structure of the target directory is as follows:
Out/target/
| -- Common
| -- R (resource file)
| -- Docs
| '-- OBJ (target file)
'-- Product
'-- Generic
The common directory indicates general content, while the product indicates product content.
In the OBJ of the common directory, there are two important directories:
Apps contains the targets generated by Java applications. Each application corresponds to a sub-directory, and the APK package of the Android Application is generated based on the original file of each application. Java_libraries contains the Java library. Each library corresponds to one of the sub directories.

Therefore, we extract the file system mainly in the/out/target/product/Generic Directory. We can see that there is an OBJ directory in it and go to the OBJ directory to see it, it is an important part of the android File System:

/Obj
Apps (various applications under the/system/apps directory in the file system)
Shared_libraries (stores all dynamic libraries)
Static_libraries (stores all static databases)
Executables (stores various executable files)

Ii. Linux kernel Mount Android root file system Process Analysis

By the way, let's take a look at the kernel startup process:

/ARCH/ARM/boot/compressed/head. S:

Start:
Decompressed_kernel () // In/ARCH/ARM/boot/compressed/Misc. c
Call_kernel ()

Stext:
/Init/Main. c
Start_kernel ()
Setup_arch ()
...
Rest_init ()
Init ()
Do_basic_setup ()
Prepare_namespace ()

I am so excited that I can't talk about it, because I came to the most important interface function of mounting the root file system.

/* This is a non _ init function. force it to be noinline otherwise gcc
* Makes it inline to Init () and it becomes part of init. Text Section
*/
Static int noinline init_post (void)
{
Free_initmem ();
Unlock_kernel ();
Mark_rodata_ro ();
System_state = system_running;
Numa_default_policy ();
If (sys_open (const char _ User *) "/dev/console", o_rdwr, 0) <0)
Printk (kern_warning "Warning: Unable to open an initial console./N ");
(Void) sys_dup (0 );
(Void) sys_dup (0 );
Current-> signal-> flags | = signal_unkillable;
If (ramdisk_execute_command ){
Run_init_process (ramdisk_execute_command );
Printk (kern_warning "failed to execute % s/n", ramdisk_execute_command );
}
/*
* We try each of these until one succeeds .*
* The Bourne shell can be used instead of init if we are *
* Trying to recover a really broken machine .*/
If (execute_command ){
Run_init_process (execute_command );
Printk (kern_warning "failed to execute % S. Attempting" "defaults.../N ",
Execute_command );
}
Run_init_process ("/sbin/init ");
Run_init_process ("/etc/init ");
Run_init_process ("/bin/init ");
Run_init_process ("/bin/sh ");
Panic ("No init found. Try passing init = option to kernel .");
}

Here, we can see the line code run_init_process (execute_command );
Execute_command is a parameter passed from uboot. It is generally/init, that is, the init initialization process in the file system is called. If the init file cannot be found
Run_init_process ("/sbin/init ");
Run_init_process ("/etc/init ");
Run_init_process ("/bin/init ");
Run_init_process ("/bin/sh ");
. Otherwise, an error is returned.

Here, because our root file system starts from/linuxrc, I have to change it
If (execute_command ){
Run_init_process ("/linuxrc ");
Printk (kern_warning "failed to execute % S. Attempting"
"Defaults.../N", execute_command );
}

Android file system initialization core init. c file Analysis

The init file we mentioned above is compiled by the android source code. After compilation, the file is in/out/target/product/generic/root/

The source code is in/system/CORE/init. C.

Main functions of init. C:

(1) install the sigchld signal. (If the parent process does not wait for the child process to end, the child process will become a zombie process, occupying system resources. Therefore, the sigchld signal must be processed to recycle resources of botnets to avoid unnecessary waste of resources .)
(2) reset umask.
What is umask, please see http://www.szstudy.cn/showArticle/53978.shtml
(3) create necessary folders for rootfs and mount appropriate partitions.
/Dev (tmpfs)
/Dev/PTS (devpts)
/Dev/socket
/Proc (Proc)
/Sys (sysfs)
(4) Create/dev/null and/dev/kmsg nodes.
(5) Parse/init. RC and add all service and operation information to the linked list.
(6) extract information kernel startup parameters from/proc/cmdline and save them to global variables.
(7) obtain the information hardware information and version number from the global variables obtained in the previous step. If not, extract the information from/proc/cpuinfo and save the information to the global variables.
(8) Select/init. (hardware). RC Based on the hardware information, parse and add the service and operation information to the linked list.
There are two/init. (hardware ). RC: init. goldfish. RC and init. trout. RC and init programs will select a resolution based on the hardware information obtained in the previous step.
(9) execute the command triggered by "early-init" in the linked list.
(10) traverse the/sys folder, which is a device addition event generated by the kernel (to automatically generate a device node ).
(11) initialize the property system and import the initialization property file.
(12) Obtain Ro. debuggable from the property system. If the value is 1, The keychord listener is initialized.
(13) Open the console. If the console is not specified in cmdline, open the/dev/console
(14) Fetch the/initlogo. RLE (a memory of 565 RLE blocks). If it succeeds
/Dev/graphics/fb0 indicates the logo. If the logo is missing, set/dev/tty0 to text mode and enable/dev/tty0. The text "android" appears in the text box.
(15) determine the number of rows in the Parameter Line and set the parameters in the attribute system:
1. If bootmode is
-Factory, set Ro. factorytest to 1
-Factory2: Set Ro. factorytest to 2.
-The value of other preset Ro. factorytest is 0.
2. If the serialno parameter exists, set Ro. serialno ""
3. If you have the bootmod parameter, set Ro. bootmod. Otherwise, it is "unknown"
4. If the baseband parameter is set, set Ro. baseband. Otherwise, set it to "unknown"
5. If the carrier parameter exists, set Ro. Carrier. Otherwise, it is "unknown"
6. If the bootloader parameter exists, set Ro. bootloader to "unknown"
7. Set Ro. Hardware and
Ro. version.
(16) all the actions that are triggered as init in the response line.
(17) Start the property service and fetch some property files. This action must be performed before
The RO. Foo settings are performed later, so that/data/local. Prop cannot be copied to them.
-/System/build. Prop
-/System/Default. Prop
-/Data/local. Prop
-Obtain the presistent propertie after the primary node obtains the default property, in/data/property.
(18) create a messaging mechanism for sigchld handler Handler
(19) confirm that all initialization is completed:
Device_fd (device init completed)
Property_set_fd (property Server start is complete)
Signal_recv_fd)
(20) all the actions that are triggered by the startup line as early-boot
(21) All the boot-triggered actions in the reboot line
(22) based on the previous Property Operation identifier, all the actions that are triggered as property in the response row
(23) Note:
-Device_fd
-Property_set_fd
-Signal_recv_fd
-If keychord exists, add keychord_fd.
(24) If bootchart is supported, the bootchart is initialized.
(25) Import progress cycle:
-Reset the acceptance of the zookeeper event. The revents value is 0.
-Query and execute the action details column.
-Services that require heavy failover
-Zookeeper: indicates the event of callback.
-If the revents of signal_recv_fd is Pollin, a message is obtained and processed.
-If the revents of device_fd is Pollin, the handler uses handle_device_fd.
-If the revents of property_fd is Pollin, the handler uses handle_property_set_fd.
-If the keychord_fd revents is Pollin, the handler uses handle_keychord.
Here, the entire android file system is up.

Initialize core init. RC file Analysis

Parse/init. RC in the Red Line (5) above and add all service and operation information to the linked list.

Parse_config_file ("/init. RC"); // code in init. C (I will not post the script for/init. Rc)

Glossary:
The android initialization statement consists of four categories of statements: Actions, commands, services, and options ).
The initialization language is formed by the language symbols separated by spaces. The C-style backslash escape character can be used to insert white space to the language symbol. Double quotation marks can also be used to prevent text from being divided into multiple language symbols by spaces. When the backslash is at the end of a row, it is used as a line break.

* Starts with # (spaces are allowed before.
* Actions and services implicitly declare a new paragraph. The declaration of commands or options for all sections belongs to this section. Commands or options before the first paragraph are ignored.
* Actions and services have unique names. Classes with the same name declared after them will be treated as errors and ignored.
Actions is the name of a series of commands. Actions has a trigger used to determine when an action is executed. When an action meets the trigger condition and is not added to the queue to be executed, it is added to the end of the queue. The actions in the queue are executed in sequence, and the commands in the actions are also executed in sequence.

Init processes other activities (device creation/destruction, Property setting, and process restart) in the execution of commands ).

Actions:
On <trigger>
<Command>
<Command>
<Command>

Two Lists of important data structures, one queue.
Static list_declare (service_list );
Static list_declare (action_list );
Static list_declare (action_queue );

* All services defined by the Service keyword in the RC Script will be added to the service_list list.
* All the on key prefix items in the RC Script will be added to the action_list list. Each action list item has a list, which is used to save the commands that fall in this section.

Script parsing process:
Parse_config_file ("/init. RC ")
Int parse_config_file (const char * fN)
{
Char * data;
Data = read_file (FN, 0 );
If (! Data) Return-1;
Parse_config (FN, data );
Dump ();
Return 0;
}
Static void parse_config (const char * fN, char * s ){
...
Case t_newline:
If (nargs ){
Int kW = lookup_keyword (ARGs [0]);
If (kw_is (kW, section )){
State. parse_line (& state, 0, 0 );
Parse_new_section (& state, KW, nargs, argS );
} Else {
State. parse_line (& state, nargs, argS );
}
Nargs = 0;
}
...
}

Parse_config parses the script line by line. If the keyword type is section, parse_new_section () is executed ();
Keywords with section type: On and sevice

The keyword type is defined in the parser. C (System/CORE/init) file.
Parser. C (System/CORE/init)
# Define section 0x01
# Define command 0x02
# Define option 0x04
Keyword attributes
Capability, option, 0, 0)
Class, option, 0, 0)
Class_start, command, 1, do_class_start)
Class_stop, command, 1, do_class_stop)
Console, option, 0, 0)
Critical, option, 0, 0)
Disabled, option, 0, 0)
Domainname, command, 1, do_domainname)
Exec, command, 1, do_exec)
Export, command, 2, do_export)
Group, option, 0, 0)
Hostname, command, 1, do_hostname)
IFUP, command, 1, do_ifup)
Insmod, command, 1, do_insmod)
Import, command, 1, do_import)
Keycodes, option, 0, 0)
Mkdir, command, 1, do_mkdir)
Mount, command, 3, do_mount)
On, section, 0, 0)
Oneshot, option, 0, 0)
Onrestart, option, 0, 0)
Restart, command, 1, do_restart)
Service, section, 0, 0)
Setenv, option, 2, 0)
Setkey, command, 0, do_setkey)
Setprop, command, 2, do_setprop)
Setrlimit, command, 3, do_setrlimit)
Socket, option, 0, 0)
Start, command, 1, do_start)
Stop, command, 1, do_stop)
Trigger, command, 1, do_trigger)
Symlink, command, 1, do_symlink)
Sysclktz, command, 1, do_sysclktz)
User, option, 0, 0)
Write, command, 2, do_write)
Chown, command, 2, do_chown)
Chmod, command, 2, do_chmod)
Loglevel, command, 1, do_loglevel)
Device, command, 4, do_device)

In parse_new_section (), separate the content starting with the service or on keyword.
Analysis.
...
Case k_service:
State-> context = parse_service (State, nargs, argS );
If (State-> context ){
State-> parse_line = parse_line_service;
Return;
}
Break;
Case k_on:
State-> context = parse_action (State, nargs, argS );
If (State-> context ){
State-> parse_line = parse_line_action;
Return;
}
Break;
...

Parse content starting with the on Keyword
Static void * parse_action (struct parse_state * state, int nargs, char ** ARGs)
{
...
Act = calloc (1, sizeof (* Act ));
Act-> name = ARGs [1];
List_init (& Act-> commands );
List_add_tail (& action_list, & Act-> alist );
...
}

Parse the content starting with the service keyword
Static void * parse_service (struct parse_state * state, int nargs, char ** ARGs)
{
Struct Service * SVC;
If (nargs <3 ){
Parse_error (state, "services must have a name and a program/N ");
Return 0;
}
If (! Valid_name (ARGs [1]) {
Parse_error (state, "invalid service name '% s'/N", argS [1]);
Return 0;
}
// If the service already exists in the service_list list, it will be ignored
SVC = service_find_by_name (ARGs [1]);
If (SVC ){
Parse_error (state, "ignored duplicate definition of service '% s'/N", argS [1]);
Return 0;
}
Nargs-= 2;
SVC = calloc (1, sizeof (* SVC) + sizeof (char *) * nargs );
If (! SVC ){
Parse_error (state, "out of memory/N ");
Return 0;
}
SVC-> name = ARGs [1];
SVC-> classname = "default ";
Memcpy (SVC-> ARGs, argS + 2, sizeof (char *) * nargs );
SVC-> ARGs [nargs] = 0;
SVC-> nargs = nargs;
SVC-> onrestart. Name = "onrestart ";
List_init (& SVC-> onrestart. commands );
// Add the service to the service_list list
List_add_tail (& service_list, & SVC-> slist );
Return SVC;
}

Service representation:
Service <Name> <pathname> [<argument>] *
<Option>
<Option>
...

Apply for a service struct and then mount it to the service_list linked list. Name is the name of the service, pathname is the command executed, and argument is the command parameter. The subsequent option is used to control the properties of this service struct. parse_line_service parses the content after the service keyword and fills it in the service structure, the resolution of this service option ends when the next service or on keyword is encountered.
For example:
Service zygote/system/bin/app_process-xzygote/system/bin -- zygote -- start-system-Server
Socket zygote stream 666
Onrestart write/sys/android_power/request_state wake
Service name: zygote
Run the following command to start the service:/system/bin/app_process.
Command Parameters:-xzygote/system/bin -- zygote -- start-system-Server
Socket zygote stream 666: Creates a socket named:/dev/socket/zygote,
Type: Stream

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.