Android memory management is slightly different from Linux. One of them is the introduction of low memory killer.
1. Reason for introduction
Android is a multitasking system, that is, it can run multiple programs at the same time, which should be familiar to everyone. Generally, it takes some time to start and run a program. Therefore, to speed up running, Android will not immediately kill a program when you exit it, in this way, the program can be started soon when you run the program again. As more programs are retained in the system, the memory will be insufficient. low memory killer is used to clear related programs when the system memory is lower than a certain value, ensure that the system maintains a certain amount of idle memory.
2. Basic Principles and important concepts
Low memory killer determines the process to be released based on two principles: the importance of the process and the amount of idle memory that can be acquired by the process.
(1) The importance of a process is determined by task_struct-> signal_struct-> oom_adj.
Android divides programs into the following categories, which are in descending order of importance:
Name |
Oom_adj |
Explanation |
Foregroud_app |
0 |
The front-end program can be understood as the program you are using |
Visible_app |
1 |
Programs visible to users |
Secondary_server |
2 |
For example, QQ will run services in the background. |
Home_app |
4 |
Home is the main interface |
Hidden_app |
7 |
Hidden programs |
Content_provider |
14 |
Content provider, |
Empty_app |
15 |
Empty program, neither service nor content |
Each program has an oom_adj value. The smaller the value, the more important the program is, and the lower the possibility of being killed.
(2) The process memory is obtained through get_mm_rss. In the same oom_adj, if the memory is large, it is killed first.
(3) When is the memory low? What happens when low memory killer starts working? Android provides two Arrays: lowmem_adj and lowmem_minfree. The former stores the oom_adj threshold value, and the latter stores the minfree warning value, in page (4 K ).
Oom_adj |
Memory alert value (in 4 K) |
0 |
1536 |
1 |
2048 |
2 |
4096 |
7 |
5120 |
14 |
5632 |
15 |
6144 |
3. source code parsing
Module_init (lowmem_init );
Module_exit (lowmem_exit );
The main functions of the module are the register_shrinker and unregister_shrinker struct lowmem_shrinker. It registers the lowmem_shrink function to the shrinker linked list and calls it in mm_scan.
This function is described in detail below:
For (I = 0; I <array_size; I ++ ){
If (other_file <lowmem_minfree [I]) {
Min_adj = lowmem_adj [I];
Break;
}
}
Other_file: the number of idle memory in the system. Based on the logic above, it is determined that low memory killer needs to analyze whether or not to release processes with a value higher than (min_adj.
If (nr_to_scan <= 0 | min_adj = oom_adjust_max + 1 ){
Lowmem_print (5, "lowmem_shrink % d, % x, return % d/N ",
Nr_to_scan, gfp_mask, REM );
Return REM;
}
Determines whether the current system status requires low memory killer.
For_each_process (p ){
Struct mm_struct * mm;
Struct signal_struct * SIG;
Int oom_adj;
Task_lock (P );
Mm = p-> mm;
Sig = p-> signal;
If (! MM |! SIG ){
Task_unlock (P );
Continue;
}
Oom_adj = sig-> oom_adj;
If (oom_adj <min_adj ){
Task_unlock (P );
Continue;
}
Tasksize = get_mm_rss (mm );
Task_unlock (P );
If (tasksize <= 0)
Continue;
If (selected ){
If (oom_adj <selected_oom_adj)
Continue;
If (oom_adj = selected_oom_adj &&
Tasksize <= selected_tasksize)
Continue;
}
Selected = P;
Selected_tasksize = tasksize;
Selected_oom_adj = oom_adj;
Lowmem_print (2, "select % d (% s), adj % d, size % d, to kill/N ",
P-> PID, p-> comm, oom_adj, tasksize );
}
For a process whose sig-> oom_adj is greater than min_adj, find the process that occupies the largest memory and store it in selected.
If (selected ){
If (fatal_signal_pending (selected )){
Pr_warning ("process % d is suffering a slow death/N ",
Selected-> PID );
Read_unlock (& tasklist_lock );
Return REM;
}
Lowmem_print (1, "Send sigkill to % d (% s), adj % d, size % d/N ",
Selected-> PID, selected-> comm,
Selected_oom_adj, selected_tasksize );
Force_sig (sigkill, selected );
REM-= selected_tasksize;
}
Send the sigkill message to kill the process.
4. Configuration
Use the following two files to configure system parameters:/sys/module/lowmemorykiller/parameters/adj and/sys/module/lowmemorykiller/parameters/minfree.