Today is the first day of the first lunar month, and everything is a new beginning. As we head into the New Year, we may be launching many meaningful projects, but on this special day, let’s take a look at how Android gets started.
- Init process and init.rc
- Init syntax Description
- The Action with the Command
- The Service and Option
- Import
- Init. rc code instance
- conclusion
Init process and init.rc
The init process is where it all starts. On Android, all processes have an indeterminate process number, except the init process whose process number must be 1. Because this process is the first one to be systemized. Also, the init process controls the startup process of the entire system.
We know that Android can run on a variety of different platforms and devices. Therefore, the startup logic is not the same. To accommodate the needs of various platforms and devices, initialization of the init process is managed through the init.rc configuration file. Init. rc uses the Android Init Language as its syntax. The main entry to the configuration file is /init.rc, which imports other configuration files using the import keyword. In this case, we call these files init.rc.
/init.rc may import. Rc files from the following paths:
- ${ro.hardware}. Rc Master configuration file provided by the hardware vendor
- /system/etc/init/ Configuration file of the core system module
- /vendor /etc/init. / SoC Configuration file provided by the SoC vendor
- /odm /etc/init. / Configuration file provided by the device manufacturer
Init syntax Description
Init language, delimited by statements, delimited by Spaces, and started with “#” for comments. There are five types of expressions supported in the configuration file:
- Action: Contains a series of commands
- Command: a Command in the init language
- Service: Service started by the init process
- Option: configuration options for the service
- Import: Imports other configuration files
In this case, Action and Service must have unique names.
The Action with the Command
The syntax for Action expressions is as follows:
on <trigger> [&& <trigger>]*
<command>
<command>
<command>
Copy the code
Trigger is the Trigger on which the Action is executed, and when the Trigger condition is met, the command is executed. Triggers come in two categories:
- Event triggers: Events can be emitted by the “trigger” command or passed by the init process
QueueEventTrigger()
Function a - Property trigger: Fires when the specified property is satisfied
An Action can have multiple property triggers, but only one event trigger. Here are some examples:
on boot && property:a=b
Fired when the “boot” event occurs and property A has a value of Bon property:a=b && property:c=d
Fired when the value of attribute A is B and attribute C is d
The Command in Action is defined by the init language. All supported commands are shown in the following table:
Command | Parameter format | instructions |
---|---|---|
bootchart_init | – | Start the bootchart |
chmod | octal-mode path | Change the access permission of a file |
chown | owner group path | Change the owner and group of a file |
class_start | serviceclass | Starts a service of the specified category |
class_stop | serviceclass | Stop and disable services of a specified category |
class_reset | serviceclass | Stops services of the specified category, but does not disable them |
copy | src dst | Copy files |
domainname | name | Set the domain name |
enable | servicename | Enable Indicates a disabled service |
exec | [seclabel[user[group]]] –command [argument] * | Fork a child process to execute the specified command |
export | name value | Exporting environment variables |
hostname | name | Setting the host Name |
ifup | iterface | Bring the NIC online |
insmod | path | Installs the module at the specified path |
load_all_props | – | Load attributes from /system, /vendor, etc |
load_persist_props | – | Load persistent properties |
loglevel | level | Set the logging level for the kernel |
mkdir | path [mode] [owner] [group] | Create a directory |
mount_all | fstab [ path[-] *option] | Mount the file system and import the specified. Rc file |
mount | type device dir [ flag] * [options] | Mount a file system |
powerctl | – | Internal implementation use |
restart | service | Restart the service |
restorecon | path [ path] * | Set the security context for the file |
restorecon_recursive | path [ path] * | A recursive version of Restorecon |
rm | path | Call unlink(2) for the specified path |
rmdir | path | Delete folders |
setprop | name value | Setting property values |
setrlimit | resource cur max | Specifies the rlimit of the resource |
start | service | Start the service |
stop | service | Stop the service |
swapon_all | fstab | Call fs_mgr_swapon_all on the specified file |
symlink | target path | Creating symbolic links |
sysclktz | mins_west_of_gmt | Specifies the system clock baseline |
trigger | event | Trigger an event |
umount | path | Unmount Specifies the file system |
verity_load_state | – | Internal implementation use |
verity_update_state | mount_point | Internal implementation use |
wait | path [ timeout ] | Wait for a file to exist until time out, or return if it exists |
write | path content | Writes to the specified file |
The Service and Option
A Service is an executable that starts the init process. The service can choose to be restarted by init after it exits.
The syntax for a Service expression is as follows:
service <name> <pathname> [ <argument> ]*
<option>
<option>
Copy the code
Options are modifications to services that affect how and when the init process starts the service. All supported options are shown in the following table:
option | Parameter format | instructions |
---|---|---|
critical | – | This service is identified as a system critical service. Exiting the service for several times will cause the system to restart to recovery mode |
disabled | – | Will not start automatically with the category, you must explicitly start |
setenv | name value | Set environment variables for the started process |
socket | name type perm [user [group [seclabel]]] | Create a Unix Domain Socket |
user | username | Switch the user before performing the service |
group | groupname [ groupname] * | Switch groups before execution |
seclabel | seclabel | Switch secLabel before executing the service |
oneshot | – | One-time service, no need to restart after death |
class | name | Specify the type of service |
onrestart | – | Execute the specified command when the service restarts |
writepid | The file… | Writes the pid of the child process to the specified file |
Import
Import is a keyword, not a command. You can use this keyword to load other.rc files in.rc files. The syntax is simple:
import path
Copy the code
Path can be another. Rc file or a folder. If it is a folder, all files under that folder are imported, but it does not loop through files in subdirectories.
Init. rc code instance
The AOSP contains the most basic. Rc files required by the Android system, which are located at /system/core/rootdir/.
We’ve picked up a snippet or two to get a feel for it:
# /system/core/rootdir/init.rc import /init.environ.rc import /init.usb.rc import /init.${ro.hardware}.rc import /init.usb.configfs.rc import /init.${ro.zygote}.rc on early-init # Set init and its forked children's oom_adj. write /proc/1/oom_score_adj -1000 # Disable sysrq from keyboard write /proc/sys/kernel/sysrq 0 # Set the security context of /adb_keys if present. restorecon /adb_keys # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628. mkdir /mnt 0775 root system # Set the security context of /postinstall if present. restorecon /postinstall start ueventd on init sysclktz 0 # Mix device-specific information into the entropy pool copy /proc/cmdline /dev/urandom copy /default.prop /dev/urandom # Backward compatibility. symlink /system/etc /etc symlink /sys/kernel/debug /d # Link /vendor to /system/vendor for devices without a vendor partition. symlink /system/vendor /vendor ...Copy the code
This is the initial code snippet in the root /init.rc file. With that in mind, this code should be fairly straightforward. In this code:
- Several other.rc files are introduced through the import keyword
- Set an Action with an event of Early-init
- Set an Action for the event init
Both events “eraly-init” and “init” are emitted by the init process.
Let’s look at another code snippet:
# /system/core/rootdir/init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
Copy the code
This code defines a Service named zygote, which is started with the executable /system/bin/app_process, passing arguments: -Xzygote /system/bin –zygote –start-system-server.
Zygote, which means “fertilized egg” in Chinese, is one of the most important services in Android. This is a very suggestive name: all application processes are children of the Zygote fork, so the Zygote process is the parent of all application processes.
We’ve covered Zygote in another article, but see the Zygote process here for a review.
conclusion
Android system is an operating system across a variety of devices, from the initial development of the system to the use of the end user, which has experienced many development processes. The developers of each process have the potential to customize the system to varying degrees.
The designers of the Android system had this complexity in mind from the start, and this is evident in the design of many of the system’s modules. A good example is the system startup mechanism: there is a mechanism for developers at different stages to adjust and expand, without modifying any source code, on the premise of ensuring the order of the system’s core services.
This kind of observance of the “open and close principle” is very worthy of our learning.