皮皮网
皮皮网

【igmp源码分析】【东乡麻将源码】【底层hmap源码】zygote源码设置

来源:浪花APP源码 发表时间:2024-12-24 10:11:43

1.T32 使用技巧
2.Android系统启动-SystemServer进程
3.Android中如何解决侧拉栏与主界面的源码重叠
4.AndroidFramework 之启动 ServiceManager
5.Android Framework源码解析,看这一篇就够了

zygote源码设置

T32 使用技巧

       探索T使用技巧,设置了解zygote进程mapping framework-res.apk文件的源码用户态虚拟地址映射原理。通过查看文件页名称,设置发现v.w结构体中vm_file为NULL,源码表示匿名页在用户地址空间。设置igmp源码分析通过输入进程名查看特定用户空间虚拟地址映射,源码发现与物理页内容一致,设置表明这部分内容属于framework-res.apk文件。源码T工具可以执行脚本,设置扫描并打印所有任务及其vma信息,源码但此处无法展示具体内容。设置在内存中搜索野指针所属进程时,源码使用data.find命令。设置使用手工恢复container_of功能,源码便于查看复杂结构体关系。T培训内容包括Attach命令、显示当前PC运行指令、东乡麻将源码数据dump、查看全局变量结构体、查看static局部静态全局变量、结构体类型解析、断点设置等。断点类型包括onchip和SOFT,后者在某些情况下可能无法正常触发。了解数据关于ARM流水线的解析,包括指令执行顺序、数据访问方式。T命令load和d.load.bin用于加载二进制文件到指定地址,用于加载Linux内核等。虚拟地址连续性在应用层函数中展示,内存管理需进一步学习。使用source code路径设置匹配源码和汇编,优化调试体验。通过这些技巧,底层hmap源码开发者可以更高效地利用T工具进行调试和分析。

Android系统启动-SystemServer进程

        相关源码文件:

        根据上篇 Android系统启动-Zygote进程

        文章,在Zygote进程启动时,会调用 ZygoteInit.main() 方法,其中分别会调用 registerZygoteSocket、preload 、startSystemServer 、runSelectLoop 来创建服务Socket、提前加载资源、创建SystemServer进程、循环创建子进程。

        本篇文章讲解 startSystemServer() 方法,在startSystemServer()方法中主要完成两件事:

· 创建SystemServer进程

        · SystemServer进程启动系统服务

        下图则是startSystemServer方法的创建过程,先通过 Zygote.forkSystemServe 去创建SystemServer进程,创建SystemServer进程之后,通过 handleSystemServerProcess() 在SystemServer进程中去启动服务。

        Zygote.forkSystemServer:

        创建 SystemServer 进程是通过 com.android.internal.os. Zygote 的 nativeForkSystemServer 本地方法创建的,JNI方法的注册在 AndroidRuntime 中,通过查询[包名]_[类名]可以知道对应的方法为:com_android_internal_os_Zygote.cpp类的com_android_internal_os_Zygote_nativeForkAndSpecialize()方法。最后通过 ForkAndSpecializeCommon 方法 fork() 创建SystemServer进程。

        handleSystemServerProcess(parsedArgs)

        通过一连串的分析得知,一是通过 nativeZygoteInit 去启动Bind,二是通过 applicationInit 方法通过异常去反射执行 SystemServer.main 方法,这里为什么需要通过异常去反射执行方法呢?为什么不直接反射执行方法?其实是为了清空栈的信息。到这里并没有启动服务,接下来的 SystemServer.main 方法是启动服务的开始。

        SystemServer.main

        SystemServer执行 main() 方法后调用 run 方法,之后分别调用 startBootstrapServices 、 startCoreServices 、 startOtherServices 开始启动很多服务,像常见的ActivityManagerService、PackageManagerService、WindowManagerService、InputManagerServic服务都在这里开启。

        开启服务有两种方式:

        但是发现最终都是调用到LocalServices.addService这种方法。

        可见启动服务是靠Binder驱动去开启的。

        首先通过JNI的注册方法去创建SystemServer进程,创建进程之后,开始处理SystemServer进程,通过异常反射调用SystemServer的main方法,主要完成两件事:一、启动Binder驱动线程,二、开启服务(AMS、PMS、WMS、IMS等),最后通过Binder驱动去启动服务。

Android中如何解决侧拉栏与主界面的重叠

       你要定制一个Android系统,你想用你自己的Launcher(Home)作主界面来替换Android自己的Home,而且不希望用户安装的Launcher来替换掉你的Launcher.

       我们可以通过修改Framework来实现这样的功能。

       这里以Android2.1的源代码为例来实际说明。

       1)首先了解一下Android的启动过程。

       Android系统的启动先从Zygote开始启动,然后......(中间的过程就不说了).....一直到了SystemServer(framework)这个地方,看到这段代码:

       /

**

       * This method is called from Zygote to initialize the system. This will cause the native

       * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back

       * up into init2() to start the Android services.

       */

       native public static void init1(String[] args);

       public static void main(String[] args) {

       if (SamplingProfilerIntegration.isEnabled()) {

       SamplingProfilerIntegration.start();

       timer = new Timer();

       timer.schedule(new TimerTask() {

       @Override

       public void run() {

       SamplingProfilerIntegration.writeSnapshot("system_server");

       }

       }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);

       }

       // The system server has to run all of the time, so it needs to be

       // as efficient as possible with its memory usage.

       VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

       System.loadLibrary("android_servers");

       init1(args);

       }

       public static final void init2() {

       Log.i(TAG, "Entered the Android system server!");

       Thread thr = new ServerThread();

       thr.setName("android.server.ServerThread");

       thr.start();

       }

       }

       从SystemServer的main函数开始启动各种服务。

       首先启动init1,然后启动init2.

       从上面的注释可以看到:init1这个方法时被Zygote调用来初始化系统的,init1会启动native的服务如SurfaceFlinger,AudioFlinger等等,这些工作做完以后会回调init2来启动Android的service。

       这里我们主要来关注init2的过程。

       init2中启动ServerThread线程,

       ServerThread中启动了一系列的服务,比如这些:

       ActivityManagerService

       EntropyService

       PowerManagerService

       TelephonyRegistry

       PackageManagerService

       AccountManagerService

       BatteryService

       HardwareService

       Watchdog

       SensorService

       BluetoothService

       StatusBarService

       ClipboardService

       InputMethodManagerService

       NetStatService

       ConnectivityService

       AccessibilityManagerService

       NotificationManagerService

       MountService

       DeviceStorageMonitorService

       LocationManagerService

       SearchManagerService

       FallbackCheckinService

       WallpaperManagerService

       AudioService

       BackupManagerService

       AppWidgetService

       这些大大小小的服务起来以后,开始

       ((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()

       在systemReady后开始开始启动Launcher。牛牛仓储源码

       在寻找Launcher的时候是根据HOME的filter(在Manifest中定义的<category android:name="android.intent.category.HOME" />)来过滤。

       然后根据filter出来的HOME来启动,如果只有一个HOME,则启动这个HOME,如果用户自己装了HOME,那就会弹出来一个列表供用户选择。

       我们现在希望从这里弹出我们自己定制的Launcher,同时也不希望弹出选择HOME的界面,我们不希望用户修改我们的home,比如我们的home上放了好多广告,以及强制安装的程序,不希望用户把它干掉。

       我们可以通过这样来实现:

       2) 定义一个私有的filter选项,然后用这个选项来过滤HOME.

       一般情况下我们使用Manifest中定义的<category android:name="android.intent.category.HOME"来过滤的,我们现在增加一个私有的HOME_FIRST过滤。

       在Intent.java(frameworks/base/core/java/android/content/Intent.java)中添加两行代码

       //lixinso:添加CATEGORY_HOME_FIRST

       @SdkConstant(SdkConstantType.INTENT_CATEGORY)

       public static final String CATEGORY_HOME_FIRST = "android.intent.category.HOME_FIRST";

       3)修改和CATEGORY_HOME相关的所有的地方,都改成HOME_FIRST,主要是ise 源码打包framework中的这几个地方:

       frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中

       //intent.addCategory(Intent.CATEGORY_HOME);

       改成intent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso:

       //if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {

       改成if (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)) { //lixinso: Intent.CATEGORY_HOME -> Intent.CATEGORY_HOME_FIRST

       frameworks/base/services/java/com/android/server/am/HistoryRecorder.java中

       // _intent.hasCategory(Intent.CATEGORY_HOME) &&

       改成 _intent.hasCategory(Intent.CATEGORY_HOME_FIRST) && //lixinso: Intent.CATEGORY_HOME->Intent.CATEGORY_HOME_FIRST

       frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java中

       //mHomeIntent.addCategory(Intent.CATEGORY_HOME);

       改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso

       frameworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.java中

       //new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);

       改成 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso

       frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java中

       //mHomeIntent.addCategory(Intent.CATEGORY_HOME);

       改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso

       frameworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.java中

       //ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);

       改成 ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso

       4) 写一个自己的Launcher.

       可以参考android sample中的Launcher,或者android源代码中的 /packages/apps/Launcher 来写。

       在Launcher中标记其是不是Launcher的最关键的代码时Manifest中的filter:android:name="android.intent.category.HOME"

       现在我们定义了自己的filter,那么,我们在我们自己写的Launcher中将Manifest改为:

       <application android:process="android.process.acore3" android:icon="@drawable/icon" android:label="@string/app_name">

       <activity android:name=".FirstAppActivity"

       android:label="@string/app_name">

       <intent-filter>

       <action android:name="android.intent.action.MAIN" />

       <category android:name="android.intent.category.HOME_FIRST" />

       <category android:name="android.intent.category.DEFAULT" />

       <category android:name="android.intent.category.MONKEY" />

       </intent-filter>

       </activity>

       </application>

       然后将编译好的apk放到/out/target/product/generic/system/app目录下。

       5)将Android自带的Launcher删除掉,包括源代码(packages/apps/Launcher)和apk(/out/target/product/generic/system/app/Launcher.apk)。

       6)

       做完这些工作,就可以重新编译Android了,我们可以编译修改过的几个相关的包。

       如果之前编译过了Android源码,可以用mmm命令来编译部分的改动。

       这里需要这样编译:

       $ . build/envsetup.sh

       $ mmm frameworks/base

       $ mmm frameworks/base/services/java

       $ mmm frameworks/policies/base/mid

       $ mmm frameworks/policies/base/phone

       7)

       编译完成后重新生成img文件。

       $ make snod

       8) 现在可以启动Android模拟器来看效果了。

       首先设置环境变量:

       $ export ANDROID_PRODUCT_OUT= ./out/target/product/generic

       然后切换到

       $ cd ./out/host/linux-x/bin

       运行

       $ ./emulator

       这样我们启动的模拟器里面用的image就是我们刚才编译好的自己定制的东西了。

       从模拟器上可以看到启动的Launcher是我们自己的Launcher,不会出现默认的Launcher了,也不会出现选择界面。

       9)我们再验证一下,如果用户装上了一个其他的Launcher(Home)会怎么样。

       从网上找一个一般的Launcher或者自己写一个一般的Launcher装上去,重新启动,不会出现选择界面。

       按HOME键也不会出来两个HOME来选择。

AndroidFramework 之启动 ServiceManager

        本文源码基于 Android ,涉及相关源码如下。

        ServiceManagaer 是 Binder 的守护进程,在 Binder 机制中起着重要的作用。本文将从源码的角度对其进行分析,整体流程如下:

        时序图如下。

        先来看看 ServiceManager 是如何启动的:

        在 Zygote 一文中说过, init 进程启动的第二阶段会解析 init.rc 文件。

        在这之后会触发 trigger init 。

        结合 init.rc 看看 action init 做了什么。

        当触发 trigger init 后,会启动 servicemanager 服务,其声明如下。

        对应的执行文件为 /system/bin/servicemanager ,在编译前位于 frameworks/native/cmds/servicemanager 下,来看看 Android.bp 。

        其对应的源码为 service_manager.c 和 binder.c ,入口函数 main() 位于 servicemanager.c 。

        启动完 ServiceManager 后会打开 Binder 驱动。

        在 main() 中首先调用 binder_open() 。

        binder_open() 主要做了如下事情:

        给结构体 binder_state 分配内存。

        系统调用 open() 打开 /dev/binder ,如果打开驱动失败,则执行 fail_open 释放内存。

        简单的解释一下什么是系统调用?

        由于需要限制不同的程序之间的访问能力,防止程序获取别的程序的内存数据, CPU 划分出两个权限等级,用户态和 内核态。

        所有的用户程序都是运行在用户态,但有时需要做一些内核态的事情,而唯一可以做这些事情的就是操作系统,所以程序需要向操作系统发起请求,以程序的名字来执行这些操作。这时就需要一个从用户态切换到内核态但不能控制内核态中执行的机制,这种机制就是 系统调用。

        系统调用 ioctl() 传入 BINDER_VERSION 命令获取 Binder 驱动版本,对比版本是否一致,不一致则执行 fail_open 释放内存。

        系统调用 mmap() 映射 kb 的内存空间,即把 Binder 驱动文件的 kb 映射到内存空间供 ServiceManager 使用,内存映射失败则执行 fail_map ,关闭 fd 并释放内存。

        ServiceManager 进程 mmap 的内存大小可以通过 adb shell 命令查看。

        可以看到内存映射地址为 0xff ~ 0xf ,差为 0x 即十进制的 kb 。

        打开 Binder 驱动后会将 ServiceManager 设置为上下文管理者。

        调用 binder_become_context_manager() 。

        android 新增 BINDER_SET_CONTEXT_MGR_EXT 命令来设置安全的上下文管理者,如果设置失败,则使用原有的 BINDER_SET_CONTEXT_MGR 命令来设置上下文管理者,两者区别在于是否携带参数。

        最后会进入循环,从 Binder 驱动读取和解析数据。

        调用 binder_loop() 进入循环,不断地通过系统调用 ioctl() 从 Binder 驱动读取数据,并通过 binder_parse() 进行数据解析。

        注意这里调用 binder_loop() 传入的 svcmgr_handler() ,后面会使用到。

        binder_write() 会封装 struct binder_write_read ,并通过系统调用 ioctl() 将对应的命令传递给 Binder 驱动。

        binder_parse() 用来解析从 Binder 驱动读取到的数据,然后根据不同的命令执行对应的操作。

        因为 cmd 命令可能有多个,所以通过 while 循环每次处理一个 cmd 命令,多 cmd 的结构大致如下图所示。

        这里重点看下 BR_TRANSACTION 命令。

        BR_TRANSACTION 是 Binder 驱动向 Server 端发送请求数据。

        binder_transaction_data 的结构如下,其表明了 transcation 传输的具体语义,语义码记录在 code 中,不同语义码携带的数据是不同的,这些数据由 data 指定。

        在解析完 binder_transaction_data 的具体语义后,会调用前面传给 binder_loop() 的 svcmgr_handler() ,其实就是 switch case 语义码做不同的事情。

        ServiceManager 的功能其实很简单:

        至此 ServiceManager 就分析完了。

Android Framework源码解析,看这一篇就够了

       深入解析Android Framework源码,理解底层原理是Android开发者的关键。本文将带你快速入门Android Framework的层次架构,从上至下分为四层,掌握Android系统启动流程,了解Binder的进程间通信机制,剖析Handler、AMS、WMS、Surface、SurfaceFlinger、PKMS、InputManagerService、DisplayManagerService等核心组件的工作原理。《Android Framework源码开发揭秘》学习手册,全面深入地讲解Android框架初始化过程及主要组件操作,适合有一定Android应用开发经验的开发者,旨在帮助开发者更好地理解Android应用程序设计与开发的核心概念和技术。通过本手册的学习,将能迅速掌握Android Framework的关键知识,为面试和实际项目提供有力支持。

       系统启动流程分析覆盖了Android系统层次角度的三个阶段:Linux系统层、Android系统服务层、Zygote进程模型。理解这些阶段的关键知识,对于深入理解Android框架的启动过程至关重要。

       Binder作为进程间通信的重要机制,在Android中扮演着驱动的角色。它支持多种进程间通信场景,包括系统类的打电话、闹钟等,以及自己创建的WebView、视频播放、音频播放、大图浏览等应用功能。

       Handler源码解析,揭示了Android中事件处理机制的核心。深入理解Handler,对于构建响应式且高效的Android应用至关重要。

       AMS(Activity Manager Service)源码解析,探究Activity管理和生命周期控制的原理。掌握AMS的实现细节,有助于优化应用的用户体验和性能。

       WMS(Window Manager Service)源码解析,了解窗口管理、布局和显示策略的实现。深入理解WMS,对于构建美观且高效的用户界面至关重要。

       Surface源码解析,揭示了图形渲染和显示管理的核心。Surface是Android系统中进行图形渲染和显示的基础组件,掌握其原理对于开发高质量的图形应用至关重要。

       基于Android.0的SurfaceFlinger源码解析,探索图形渲染引擎的实现细节。SurfaceFlinger是Android系统中的图形渲染核心组件,理解其工作原理对于性能优化有极大帮助。

       PKMS(Power Manager Service)源码解析,深入理解电池管理策略。掌握PKMS的实现,对于开发节能且响应迅速的应用至关重要。

       InputManagerService源码解析,揭示了触摸、键盘输入等事件处理的核心机制。深入理解InputManagerService,对于构建响应式且用户体验优秀的应用至关重要。

       DisplayManagerService源码解析,探究显示设备管理策略。了解DisplayManagerService的工作原理,有助于优化应用的显示性能和用户体验。

       如果你对以上内容感兴趣,点击下方卡片即可免费领取《Android Framework源码开发揭秘》学习手册,开始你的Android框架深入学习之旅!

相关栏目:焦点