Reprint!
Init is the first process initiated by Linux kernel, and understanding of init is important for familiarity with the Android system.
Each Android directory has a very important file android.mk, which is responsible for compiling the code below the directory.
System/core/init/android.mk
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > </span><span style="FONT-SIZE:18PX;" ><span style="color: #ff0000;" >local_module:= Init
- </span>
- Local_force_static_executable: = true
- Local_module_path: = $ (target_root_out)
- <span style="color: #ff0000;" >include $ (build_executable</span>)
- Symlinks: = $ (target_root_out)/sbin/ueventd
- $ (symlinks): init_binary: = $ (Local_module)
- $ (symlinks): $ (local_installed_module) $ (local_path)/android.mk
- @echo "Symlink: [email protected]. /$ (init_binary) "
- @mkdir-P $ (dir [email protected])
- @rm-RF [email protected]
- </span><span style="Font-size:18px;color: #ff0000;" >$ (hide) ln-sf. /$ (init_binary) [email protected]
- </span>
The code above generates an executable called Init, which will be placed in/below, and will produce a symbolic link/sbin/eventd, pointing to/init. We can't help but ask, why do you do this?
Init is a script interpreter that parses two files under the target system,
/init.rc
/init.xxx.rc (XXX stands for Platform platform name)
First look at the source code directory/device/xxx/init.rc
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > On Early-init
- Start Ueventd
- </span>
It seems that Init started its own process when parsing the script, but the process name became UEVENTD.
System/core/init/init.c/main
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > if (!strcmp (basename (argv[0]), "Ueventd"))
- return Ueventd_main (argc, argv);
- </span>
The program execution path differs depending on the process name. Ueventd as the name implies should be to receive uvent daemon, here its main role is to create or delete/dev/xxx (XXX device name) under Uevent, we know that under Linux to create a Device node interface Mknod, Let's go in and see where this interface is called.
System/core/init/ueventd.c/ueventd_main
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" >ueventd_parse_config_file ("/ueventd.rc");
- SNPRINTF (TMP, sizeof (TMP), "/ueventd.%s.rc", hardware);
- Ueventd_parse_config_file (TMP);
- Device_init ();
- </span>
UEVENTD has two scripts to parse, ueventd.rc,ueventd.xxx.rc, script, and script this script allows the client to set permissions for the/dev or/sys directories and subdirectories.
System/core/rootdir/ueventd.rc
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" >/dev/binder 0666 root root</span>
Note here that Ueventd_parse_config_file does not create a device node, it is intended to provide a database, and when a device node is generated, EVENTD will refer to this database to set the device node's permissions.
System/core/init/devices.c/device_init
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > device_fd = Open_uevent_socket ();
- Coldboot ("/sys/class");
- Coldboot ("/sys/block");
- Coldboot ("/sys/devices");
- </span>
This function is very simple, the main is to create a uevent socket handle, while triggering/sys/clas,/sys/block,/sys/devices these three directories and their subdirectories uevent, and then accept and create the device node, At this point the device node is created, coldboot inside there is a very interesting function do_coldboot, this is a recursive call function, the implementation is very interesting, we can look at.
System/core/init/ueventd.c/ueventd_main
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > While (1) {
- ufd.revents = 0;
- NR = Poll (&UFD, 1,-1);
- if (nr <= 0)
- continue;
- if (ufd.revents = = Pollin)
- HANDLE_DEVICE_FD ();
- }
- </span>
The dead loop, accepting kernel uevent, dynamically create or delete nodes.
HANDLE_DEVICE_FD will eventually call Mknod to create the device node, as follows:
handle_device_fd-> handle_device_event-> make_device-> Mknod
Android Init process-uevent