Análisis del mecanismo LowMemoryKiller
Cuando la memoria disponible del sistema Linux es baja, el mecanismo Oom Killer eliminará algunos procesos de acuerdo con ciertas reglas para liberar memoria, y el mecanismo LowMemoryKiller del sistema Android ha realizado algunos ajustes en función de esta función. . La aplicación en el sistema Android no se cerrará inmediatamente después de su uso, sino que residirá en la memoria. La próxima vez que ingrese a la aplicación aquí, podrá guardar el proceso de creación de un proceso y acelerar la velocidad de inicio. El mecanismo LowMemoryKiller eliminará algunos procesos para recuperar memoria cuando los recursos de memoria sean escasos.
El mecanismo LowMemoryKiller se divide en tres partes
ProcessList en Framework y el proceso Native lmkd se comunican a través de Socket, mientras que lmkd y LowMemoryKiller en el kernel escriben en el nodo de archivo a través de writeFileString. Los métodos de contenido se comunican.
La capa Framework ajusta el valor adj y el umbral de espacio de memoria del proceso a través de ciertas reglas y luego lo envía al proceso lmkd a través del socket. Hay dos métodos de procesamiento de lmkd. valor umbral al nodo del archivo y enviarlo al LowMemoryKiller del kernel se utiliza para eliminar procesos por parte del kernel. La otra es que lmkd monitorea el uso de la memoria a través de cgroup y calcula el proceso a eliminar por sí mismo.
lmkd es un proceso nativo, iniciado por el proceso init, definido en /system/core/lmkd/lmkd.rc
En lmkd.rc, el proceso lmkd se inicia y Creó un descriptor de socket llamado lmkd para la comunicación entre procesos de socket. Después de que se inicia lmkd, primero ejecuta el método principal.
El método principal primero establece las reglas de programación del proceso actual y luego ejecuta el método init y el método mainLoop.
El trabajo realizado en el método init de lmkd
Primero analizamos el mecanismo de eliminación del proceso LowMemoryKiller implementado por el kernel y luego analizamos el mecanismo implementado por lmkd. El resultado final de ambos es eliminar algunos procesos para liberar memoria cuando la memoria es escasa, pero los mecanismos de implementación son diferentes.
Una vez completada la inicialización de init, ingrese el método mainloop y espere en un bucle hasta que se informe el evento epoll. Durante el inicio, epoll monitorea la conexión del socket. Cuando hay una conexión de socket, ctrl_connect_handler. Se llamará al método.
Al escuchar la conexión del socket, sabemos que el cliente de socket conectado a lmkd en este momento es el marco. Cuando llega una conexión, el método de aceptación devuelve el socketFD conectado, y luego también se agrega el socketFD conectado. para epoll. Cuando socketFD Hay un mensaje legible, es decir, cuando el marco envía un mensaje a lmkd, epoll se activa y luego descarta el método ctrl_data_handler para procesarlo.
Los procesos Framework y lmkd se comunican entre procesos a través de sockets. Cuando se inicializa lmkd, espera los mensajes enviados por Framework escuchando el descriptor de socket lmkd.
Hay tres métodos relacionados con el envío de comandos de Framework a lmkd.
En las tres situaciones anteriores, Framework finalmente envió tres mensajes a lmkd a través del socket.
Lógica de procesamiento de comandos de recepción de lmkd
lmkd monitorea si hay datos en el socket a través de epoll. Después de aceptar el comando de socket enviado por el marco, llama al método ctrl_cmmand_handler para mostrarlo y analizarlo. el comando en el socket y los parámetros, se llaman diferentes métodos según el comando.
Hay dos formas de implementar la eliminación de procesos. Una es el LMK del kernel, que utiliza un reductor para activar el reciclaje de memoria baja. La otra es lmkd, que monitorea el uso de la memoria a través de cgroups y calcula y elimina los procesos por sí mismo. Las dos implementaciones no son iguales y deben analizarse una por una.
Establecer el umbral de memoria y el valor adj significa encapsular los datos recibidos del marco en una cadena y escribirlos en dos nodos de archivo a través de writefilestring para que los use el kernel LMK.
/sys/module/lowmemorykiller/parameters/minfree: Límite de nivel de memoria
/sys/module/lowmemorykiller/parameters/adj: Límite de nivel de memoria correspondiente al proceso a eliminar adj value.
Dado que se utiliza el kernel LMK, la prioridad del proceso se puede ajustar escribiendo directamente la prioridad en el archivo oom_adj_score del proceso correspondiente.
No es necesario hacer nada al eliminar un proceso.
En Linux, hay un subproceso del kernel llamado kswapd. Cuando Linux recupera y almacena páginas, el subproceso kswapd atravesará un reductor. lista vinculada y se ejecuta una devolución de llamada, o cuando se inicia una aplicación y se determina que la memoria disponible es insuficiente, el kernel bloqueará el proceso de asignación de memoria por parte del proceso que solicitó la asignación de memoria y ejecutará lowmemorykiller en el proceso para liberar la memoria. Aunque no he tenido contacto con él antes, el entendimiento general es que después de registrar esta función de devolución de llamada reductora en el sistema, esta función de devolución de llamada se llamará cuando el sistema no tenga suficientes páginas de memoria libre. La definición de reductor de estructura está en linux/kernel/include/linux/shrinker.h:
El proceso de registro del reductor de LowMemoryKiller del kernel es el siguiente:
Una vez completado el registro , cuando la memoria es escasa, se volverá a llamar a Shrinker, el más importante de los cuales es el método lowmem_scan. La implementación específica es la siguiente:
El principio del kernel LMK es muy simple: primero registre el reductor y, cuando la memoria sea escasa, se activará el método lowmem_scan. Lo que hace este método es encontrar un proceso. , luego elimínelo y libere algo de memoria.
Se ha analizado la lógica de implementación del kernel LMK.
La forma en que lmkd implementa la verificación de memoria se basa en la memoria de cgroup.
¿Qué es la memoria cgroup?
El subsistema de memoria de Cgroup, es decir, memoria cgroup (en lo sucesivo, memcg en este artículo), proporciona gestión del comportamiento de la memoria de un grupo de procesos. en el sistema, diferenciando y administrando procesos o aplicaciones que tienen diferentes requisitos de memoria en todo el sistema para lograr una utilización y aislamiento de recursos más efectivos.
archivos relacionados con la memoria de cgroup
Comprendamos brevemente el principio de cgroup y luego veamos el método init de lmkd
Primero comprenda el uso de la memoria Pressure_level
p>El método init_mp_common sigue estrictamente el uso de Pressure_level y registra la devolución de llamada del evento de Pressure_level. Pressure_level se divide en tres niveles
Cuando la memoria alcanza el nivel correspondiente, el método mp_event_common lo hará. ser llamado nuevamente por el método mp_event_common para manejar.
Principio de verificación y eliminación de memoria de lmkd:
Los dos métodos de implementación de verificación y eliminación de procesos tienen principios similares. Ambos registran devoluciones de llamada. Cuando la memoria es escasa, el ajuste. Se comprueba la memoria restante. Elimina la memoria mayor que el adj. El método de reducción del núcleo solo liberará memoria cuando la memoria sea escasa, mientras que el método cgroup tiene un control más preciso y activa el reciclaje de memoria según diferentes niveles.