Red de conocimiento informático - Computadora portátil - Iniciar ServiceManager en AndroidFramework

Iniciar ServiceManager en AndroidFramework

Este artículo se basa en el código fuente de Android 10. El código fuente relevante es el siguiente.

ServiceManagaer es el proceso demonio de Binder y juega un papel importante en el mecanismo de Binder. Este artículo lo analizará desde la perspectiva del código fuente. El proceso general es el siguiente:

El diagrama de tiempo es el siguiente.

Veamos cómo se inicia ServiceManager:

Como se menciona en el artículo de Zygote, el proceso init analiza el archivo init.rc durante la segunda fase del inicio.

Después de eso, se activará el disparador init.

Consulte la combinación de acción init e init.rc.

Cuando se activa el activador init, el servicio servicemanager se iniciará con la siguiente declaración.

El archivo ejecutable correspondiente es /system/bin/servicemanager, que se encuentra en frameworks/native/cmds/servicemanager antes de la compilación, así que verifique Android.bp.

Los códigos fuente correspondientes son service_manager.c y binder.c, y la función de entrada main() se encuentra en servicemanager.c.

Iniciar servicemanager es una cuestión sencilla.

Después de iniciar ServiceManager, se abrirá el controlador de Binder.

Primera llamada a binder_open() en main().

binder_open() hace lo siguiente:

Asigna memoria para la estructura binder_state.

El sistema llama a open() para abrir /dev/binder. Si el controlador no se puede abrir, se ejecuta fail_open para liberar la memoria.

Explica brevemente ¿qué es una llamada al sistema?

Debido a la necesidad de limitar los derechos de acceso entre diferentes programas y evitar que los programas accedan a los datos de la memoria de otros programas, la CPU se divide en dos niveles de permisos: usuario y kernel.

Todos los programas de usuario se ejecutan en modo usuario, pero a veces necesitan realizar operaciones en modo kernel, y lo único que puede realizar estas operaciones es el sistema operativo, por lo que el programa necesita realizar una solicitud al sistema operativo. sistema para realizar estas operaciones nominalmente. Esto requiere un mecanismo para cambiar del modo de usuario al modo kernel, pero no controla la ejecución del modo kernel. Esta es una llamada al sistema.

La llamada al sistema ioctl() pasa el comando BINDER_VERSION para obtener la versión del controlador Binder, compara las versiones para verificar la coherencia y luego realiza un fail_open para liberar la memoria.

El sistema llama a mmap() para asignar 128 kb de espacio de memoria, es decir, el archivo del controlador Binder de 128 kb se asigna al espacio de memoria que ServiceManager puede usar. Si la asignación de memoria falla, se ejecuta fail_map, se cierra fd y se libera la memoria.

Puede utilizar el comando adb shell para ver el tamaño de la memoria mmap del proceso ServiceManager.

Puedes ver que la dirección de mapeo de memoria es 0xf10f8000 ~ 0xf1118000, una diferencia de 0x20000, que es 128kb en decimal.

Abra el controlador de Binder y configure ServiceManager como administrador de contexto.

Llame a binder_become_context_manager().

Android 10 tiene un nuevo comando BINDER_SET_CONTEXT_MGR_EXT para configurar el administrador de contexto de seguridad. Si la configuración falla, se usa el comando BINDER_SET_CONTEXT_MGR original para configurar el administrador de contexto.

Finalmente, se ingresa un bucle para leer y analizar los datos del controlador Binder.

Llamar a binder_loop() ingresará a un bucle que lee continuamente datos del controlador de Binder a través de la llamada al sistema ioctl() y analiza los datos a través de binder_parse().

Tenga en cuenta que binder_loop() se pasa a svcmgr_handler(), que se utilizará más adelante.

binder_write() encapsula la estructura binder_write_read y pasa el comando correspondiente al controlador de Binder a través de la llamada al sistema ioctl().

binder_parse() se utiliza para analizar los datos leídos del controlador Binder y luego realizar las operaciones correspondientes de acuerdo con el comando.

Dado que puede haber más de un comando cmd, la estructura de múltiples comandos cmd es aproximadamente como se muestra en la figura siguiente, es decir, se utiliza un bucle while para procesar un comando cmd a la vez.

A continuación nos centramos en el comando BR_TRANSACTION.

BR_TRANSACTION es el controlador de Binder que envía datos de solicitud al servidor.

binder_transaction_data tiene la siguiente estructura, que muestra la semántica específica de las transferencias escapadas. Los códigos semánticos se registran en el código, y diferentes códigos semánticos contienen datos diferentes, que se especifican mediante datos.

Después de analizar la semántica de binder_transaction_data, se llama al svcmgr_handler() pasado previamente a binder_loop(), que en realidad es un código semántico de cambio de caso para realizar diferentes operaciones.

La funcionalidad de ServiceManager es realmente muy simple:

Entonces ServiceManager ha realizado el análisis.

Hasta el momento se ha analizado ServiceManager.