Android系统启动过程详解

Android应用程序进程启动过程(后篇) 在前篇中我们讲到了Android应用程序进程启动过程,这一篇我们来讲遗留的知识点:在应用程序进程创建过程中会启动Binder线程池以及在应用程序进程启动后会创建消息循环。 阅读详情

前言

一直想研究Android完整的启动过程,网上看了不少资料,也看了书上的一些说明,对这些观点有些怀疑,于是自己分析了系统启动的完整过程。从内核启动第一个用户程序init开始说起,直到Home应用的启动,每一步都有源代码展示。希望能解除读者对Android系统启动过程中的困惑,若有什么疑问,欢迎留言交流。本研究基于CM10.1源码,读者若能对照源代码查看效果会更好。

1) init启动servicemanager和 zygote两个service

Android底层是Linux内核,和linux类似,内核初始化后启动的第一个用户进程是init,它会解析init.rc脚本,启动init.rc里声明的service,并执行一些action。在init.rc里有启动Andriod空间的一些关键服务,代码如下:

#…
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
#…

servicemanager负责管理所有的binder service, 这些binder service有native的,也有java的。native的binder service有surfaceflinger,drm,media等,java的binder service就有我们平常熟悉的很多管理服务了,ActivityManagerService,WindowManagerService,BatteryService,PowerManagerService,InputManagerService等等。service manager并不负责这些binder service的创建,native的binder service大多由init启动init.rc里的service时创建并启动,java层的binder service大多由zygote创建并启动的,接下来会详细这些service是如何被启动的。

2) zygote service启动java层的ZygoteInit

zygote服务是java层所有程序进程的父进程,它是Android空间程序的孵化器,Android空间所有程序都是由zygote进程启动的。zygote service对应/system/bin/app_process程序,源代码位于frameworks/base/cmds/app_process/app_main.cpp,启动时的main函数代码如下:

int main(int argc, const char* const argv[])
{
//...
/*runtime就是dalvik虚拟机实例,启动Java层应用时,
 *会fork 一个子进程,复制虚拟机,许多书上将runtime看作一个进程,
 *然后再启动zygote进程,个人觉得这是错误的 
 */		 
AppRuntime runtime;
//... 
while (i < argc) {
    const char* arg = argv[i++];
    if (!parentDir) {
        parentDir = arg;
  /*init.rc启动app_main会设置参数--zygote*/ 
    } else if (strcmp(arg, "--zygote") == 0) {
        zygote = true;
        niceName = "zygote"; //进程的名字
  /*init.rc启动app_main会设置参数--start-system-server,
   *表示需启动systemserver
   */
    } else if (strcmp(arg, "--start-system-server") == 0) {
        startSystemServer = true;
 /*启动应用时会使用--application参数*/             
    } else if (strcmp(arg, "--application") == 0) {
        application = true;
/*--nice-name=参数表示要设置的进程名字*/            
    } else if (strncmp(arg, "--nice-name=", 12) == 0) {
        niceName = arg + 12;
    } else {
        className = arg;
        break;
    }
}    
/*设置进程名*/
if (niceName && *niceName) {
    setArgv0(argv0, niceName);
    set_process_name(niceName);
}
/*设置虚拟机运行环境的父目录*/
runtime.mParentDir = parentDir;
if (zygote) {
/*虚拟机里启动com.android.internal.os.ZygoteInit,
 *并传递参数start-system-server
 */
    runtime.start("com.android.internal.os.ZygoteInit",
            startSystemServer ? "start-system-server" : "");
} else if (className) {        
    /*若不是zygote,则启动的第一个类是com.android.internal.os.RuntimeInit,
     *RumtimeInit初始化后会启动mClassName
     */
    runtime.mClassName = className;
    runtime.mArgC = argc - i;
    runtime.mArgV = argv + i;
    runtime.start("com.android.internal.os.RuntimeInit",
            application ? "application" : "tool");
} else {
    fprintf(stderr, "Error: no class name or --zygote supplied.\n");
    app_usage();
    LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    return 10;
}
//...
}


通过上述代码可知道zygote service将运行dalvik虚拟机,并在虚拟机里执行com.android.internal.os.ZygoteInit,还给它传递了参数start-system-server

3) ZygoteInit启动SystemServer

ZygoteInit启动时的相关源代码:

public static void main(String argv[]) {
{
try {   
   //...
   //在某个描述符上监听连接请求,
   //其它Android空间的程序的启动都是通过连接zygote才孵化出来的
   registerZygoteSocket();
   //... 
   if (argv[1].equals("start-system-server")) {
        //启动SystemServer
        startSystemServer();
    } else if (!argv[1].equals("")) {
        throw new RuntimeException(argv[0] + USAGE_STRING);
    }
   //...
   /*ZYGOTE_FORK_MODE默认为false,如果为true的话,每收到一个连接请求,
    *就会建立一个新进程,然后再运行连接请求所要求执行的命令,此时会建立另一个新进程
    */
    if (ZYGOTE_FORK_MODE) {
        runForkMode();
    } else {
       //使用Select poll的方式来建立新进程,收到连接请求后,也会建立进程启动某个程序
        runSelectLoopMode();
    }
 
    closeServerSocket();
} catch (MethodAndArgsCaller caller) {
    caller.run();
} catch (RuntimeException ex) {
    Log.e(TAG, "Zygote died with exception", ex);
    closeServerSocket();
    throw ex;
}
}
从上述代码可知道会调用startSystemServer以启动SystemServer,相关源代码如下:
private static boolean startSystemServer()
{
/* Hardcoded command line to start the system server */
//启动SystemServer使用的参数
String args[] = {
    "--setuid=1000",
    "--setgid=1000",
    "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,3001,3002,3003,3004,3006,3007,3009",
    "--capabilities=130104352,130104352",
    "--runtime-init",
    "--nice-name=system_server",
    //注意:就是在这里设置要启动的SystemServer包名及类名,故此后续才能启动SystemServer
    "com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
    /*将args参数传给ZygoteConnection进行转化,--形式的参数将全部被接收
     * 但是要启动的类的类名com.android.server.SystemServer会放在
     *ZygoteConnection.Arguments的remainingArgs里,后来调用handleSystemServerProcess时会用到
     */
    parsedArgs = new ZygoteConnection.Arguments(args); 
    /*添加额外运行参数*/
    ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
    ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); 
    /*开启新进程*/
    pid = Zygote.forkSystemServer(
            parsedArgs.uid, parsedArgs.gid,
            parsedArgs.gids,
            parsedArgs.debugFlags,
            null,
            parsedArgs.permittedCapabilities,
            parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
    throw new RuntimeException(ex);
} 
/* For child process */
if (pid == 0) {
	  /*调用handleSystemServerProcess会执行ZygoteConnection.Arguments的remainingArgs参数
	   *所指定的类,即com.android.server.SystemServer	   
	   */
    handleSystemServerProcess(parsedArgs);
}
}

ZygoteInit的startSystemServer会调用forkSystemServer,然后:

ZygoteInit.forkSystemServer -> Zygote.nativeForkSystemServer-> dalvik_system_Zygote.cpp 里的Dalvik_dalvik_system_Zygote_forkSystemServer-> forkAndSpecializeCommon->fork建立新进程

ZygoteInit的startSystemServer会调用handleSystemServerProcess来真正启动systemserver,相关源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
//... 
if (parsedArgs.niceName != null) {
    Process.setArgV0(parsedArgs.niceName);
}
//启动systemserver时invokeWith为null
if (parsedArgs.invokeWith != null) {
    WrapperInit.execApplication(parsedArgs.invokeWith,
            parsedArgs.niceName, parsedArgs.targetSdkVersion,
            null, parsedArgs.remainingArgs);
} else {
    /*
     * 启动systemserver时,parsedArgs.remainingArgs为com.android.server.SystemServer.
     */
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}

然后的流程是

RuntimeInit.zygoteInit-> applicationInit,applicationInit的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void applicationInit(int targetSdkVersion, String[] argv)
{
//...
final Arguments args;
try {
    //参数转换,系统启动时,argv里有一个参数是com.android.server.SystemServer
    args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
    Slog.e(TAG, ex.getMessage());
    // let the process exit
    return;
}
//...
//终于在此启动了SystemServer
invokeStaticMain(args.startClass, args.startArgs)
}

4) SystemServer 启动过程

执行com.android.server.SystemServer时,main函数里会调用init1函数,init1函数是一个本地函数,init1的实现放在frameworks/base/services/jni/com_android_server_SystemServer.cpp里,对应的jni函数是android_server_SystemServer_init1,在该函数里会调用system_init,而system_init的实现是在frameworks/base/cmds/system_server/library/system_init.cpp,该函数的实现代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
extern "C" status_t system_init()
{
//... 
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p\n", sm.get());
sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
    // Start the SurfaceFlinger
    SurfaceFlinger::instantiate();
}
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
    // Start the sensor service
    SensorService::instantiate();
}
// And now start the Android runtime.  We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
ALOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
ALOGI("System server: starting Android services.\n");
JNIEnv* env = runtime->getJNIEnv();
if (env == NULL) {
    return UNKNOWN_ERROR;
}
jclass clazz = env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
    return UNKNOWN_ERROR;
}
//反过来调用Java里SystemServer的init2函数
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
if (methodId == NULL) {
    return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz, methodId);
ALOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
ALOGI("System server: exiting thread pool.\n");
}

5) 启动Java层的各种binder service

调用SystemServer的init2函数后,会开启新线程android.server.ServerThread,在新线程里会启动各种Java层的binder service,并在service manager里注册,这些Service大多开启了新线程运行,故此都是systemserver的子线程,添加的Service列表如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
ServiceManager.addService("entropy", new EntropyMixer());
ServiceManager.addService(Context.POWER_SERVICE, power);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
ServiceManager.addService("telephony.registry", telephonyRegistry);
ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,
ServiceManager.addService(Context.USER_SERVICE,UserManagerService.getInstance());
ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);
ServiceManager.addService("battery", battery);
ServiceManager.addService("vibrator", vibrator);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,new AccessibilityManagerService(context));
ServiceManager.addService("mount", mountService);
ServiceManager.addService("lock_settings", lockSettings);
ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
ServiceManager.addService(Context.CLIPBOARD_SERVICE,new ClipboardService(context));
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms);
ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
ServiceManager.addService(Context.NSD_SERVICE, serviceDiscovery);
ServiceManager.addService(Context.THROTTLE_SERVICE, throttle);
ServiceManager.addService("fm_receiver",new FmReceiverService(context));
ServiceManager.addService("fm_transmitter",new FmTransmitterService(context));
ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,new UpdateLockService(context));
ServiceManager.addService(Context.PROFILE_SERVICE, profile);
ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);
ServiceManager.addService(DeviceStorageMonitorService.SERVICE,
ServiceManager.addService(Context.LOCATION_SERVICE, location);
ServiceManager.addService(Context.COUNTRY_DETECTOR, countryDetector);
ServiceManager.addService(Context.SEARCH_SERVICE,new SearchManagerService(context));
ServiceManager.addService(Context.DROPBOX_SERVICE,new DropBoxManagerService(context, new File("/data/system/dropbox")));
ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
ServiceManager.addService(Context.USB_SERVICE, usb);
ServiceManager.addService(Context.SERIAL_SERVICE, serial);
ServiceManager.addService(Context.BACKUP_SERVICE,new BackupManagerService(context));
ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget);
ServiceManager.addService("diskstats", new DiskStatsService(context));
ServiceManager.addService("samplingprofiler", new SamplingProfilerService(context));
ServiceManager.addService("commontime_management", commonTimeMgmtService);
ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
ServiceManager.addService("assetredirection", new AssetRedirectionManagerService(context));
ServiceManager.addService("pieservice", pieService);

上述并没有看到将ActivityManagerService添加到servicemanager管理,它的添加过程比较特别。在线程android.server.ServerThread里会调用ActivityManagerService.setSystemProcess();setSystemProcess函数的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void setSystemProcess() {
//…
ActivityManagerService m = mSelf;            
ServiceManager.addService("activity", m, true);
ServiceManager.addService("meminfo", new MemBinder(m));
ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
ServiceManager.addService("dbinfo", new DbBinder(m));
if (MONITOR_CPU_USAGE) {
    ServiceManager.addService("cpuinfo", new CpuBinder(m));
}
ServiceManager.addService("permission", new PermissionController(m));
ApplicationInfo info =
    mSelf.mContext.getPackageManager().getApplicationInfo(
                "android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info);
//…
}

可以看到ActivityManagerService采用了单例模式,并调用ServiceManager.addService(“activity”, m, true);将ActivityManagerService交给servicemanager管理,在ActivityManagerService里还添加了别的binder service,像MemBinder,GraphicsBinder,DbBinder。

最后会调用Looper.loop();进入loop循环,等待和别的程序通信。

6) 启动系统界面

线程android.server.ServerThread里有如下代码:

1
2
3
4
5
6
7
8
ActivityManagerService.self().systemReady(new Runnable() {
    public void run() {
        Slog.i(TAG, "Making services ready");
 
        if (!headless) startSystemUi(contextF);
        //...
     }
}

startSystemUi就是用于启动系统界面的,代码如下:

1
2
3
4
5
6
7
static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.OWNER);
}

这样便启动了com.android.systemui应用,该应用将启动PowerUI和RingtonePlayer两个线程。

7) 启动Home 程序

线程android.server.ServerThread里有如下代码:

1
2
3
4
5
6
7
//…
ActivityManagerService.self().systemReady(new Runnable() {
            public void run() {
                  //…
                }
    });
//…

ActivityManagerService.self().systemReady有如下代码:

1
2
3
//…
mMainStack.resumeTopActivityLocked(null);
//…

ActivityStack. resumeTopActivityLocked()有如下代码:

1
resumeTopActivityLocked(prev, null);

resumeTopActivityLocked的实现有如下代码:

1
2
3
4
5
6
7
8
9
10
//…
if (next == null) {
    // There are no more activities!  Let's just start up the
    // Launcher...
    if (mMainStack) {
        ActivityOptions.abort(options); 
        return mService.startHomeActivityLocked(mCurrentUser);
    }
}
//…

mService类型是ActivityManagerService,ActivityManagerService. startHomeActivityLocked的实现有如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
boolean startHomeActivityLocked(int userId) {
//…
Intent intent = new Intent(
    mTopAction,
    mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
//这里便添加了Intent.CATEGORY_HOME,
//所有的Home应用都会都带有该类型的Activity,只有这样才会被认为是Home应用
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
    intent.addCategory(Intent.CATEGORY_HOME);
}
ActivityInfo aInfo =
    resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
    intent.setComponent(new ComponentName(
            aInfo.applicationInfo.packageName, aInfo.name));
    // Don't do this if the home app is currently being
    // instrumented.
    aInfo = new ActivityInfo(aInfo);
    aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
    ProcessRecord app = getProcessRecordLocked(aInfo.processName,
            aInfo.applicationInfo.uid);
    if (app == null || app.instrumentationClass == null) {
        intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
        mMainStack.startActivityLocked(null, intent, null, aInfo,
                null, null, 0, 0, 0, 0, null, false, null);
    }
}
}

这样先找到使用Intent.CATEGORY_HOME声明的Activity组件,然后再调用mMainStack.startActivityLocked启动该Activity。

system server启动Home程序总结:

android.server.ServerThread->ActivityManagerService.self().systemReady->mMainStack.resumeTopActivityLocked->resumeTopActivityLocked-> mService.startHomeActivityLocked-> intent.addCategory(Intent.CATEGORY_HOME);mMainStack.startActivityLocked

总结

内核初始化好后,运行的第一个用户程序是init,init将启动init.rc里声明的多个service,跟Android空间相关的有servicemanager和zygote,servicemanager负责管理所有的binder service,zygote负责孵化所有Android空间的程序。zygote service对应的程序是app_process,不过加了一些启动参数,所以它会启动Java层的ZygoteInit,在ZygoteInit里会启动SystemServer,SystemServer分为两个阶段:本地的init1和Java层的init2,init2里会启动线程android.server.ServerThread。在android.server.ServerThread线程里会启动Java层的各种binder service,比如ActivityManagerService,PackageManagerService,WindowManagerService。然后调用ActivityManagerService的systemReady方法,在该方法里会启动系统界面以及Home程序。

Android系统启动流程(二)解析Zygote进程启动过程,讲的太透彻了 char prop[PROP_VALUE_MAX]; if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { LOG_ALWAYS_FATAL(“app_process: Unable to determine ABI list from property %s.”, ABI_LIST_PROPERTY); return 11; } String8 abiFlag("–abi-list="); abiFlag.append(prop); args.ad 阅读详情

相关推荐

【系统调试篇】1. ‘Native registration unable to find class ‘com/android/internal/os/RuntimeInit‘;

写在前面: 本系列博文主要枚举在开发AndroidAutomotiveOS过程中遇到的各种问题,比如不开机,重启,WTD,Panic等。 问题描述:编译frameworks/base/core,并push到手机重启后,无法开机,卡开机动画; 初步分析:system_server无法启动,发生tombstone,提示Abort message: 'Native registration unable to find class 'com/android/internal/os/RuntimeIni.

从0到1,突破自己 5758

Android 系统启动流程

1. Init 进程启动流程 2. Zygote启动流程 3. SystemServer启动流程 1. Init 进程启动流程 Android启动流程 init进程 –> Zygote进程 –> SystemServer进程 –> 各种应用进程 Init 进程 init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任, 一是挂载目录,比如/sys、/dev、/proc, 二是运行init.rc脚本。 init进程...

u010783226的专栏 586

表格数据学习的图神经网络综述

今天学习一篇发表在中科院一区期刊《ACM Computing Surveys》的综述文章《Graph Neural Networks for Tabular Data Learning: A Survey with Taxonomy & Directions》,该刊主要刊载计算机理论方法领域的系统性综述与教程论文,注重跨学科技术融合研究,最新的影响因子为28.0。本文的目的在于通过学习这篇文章,了解关于表格数据学习点图神经网络一些基础知识。

qq_41009600的博客 800

Android系统启动流程(一)解析init进程启动过程

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。贵在坚持!《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!return rc;

2401_84412988的博客 199

保姆级教程:用再生龙Clonezilla Live给Ubuntu系统做全盘备份与恢复(含BIOS设置避坑)

本文提供了一份详细的Clonezilla Live教程,指导Ubuntu用户如何轻松完成全盘备份与恢复。从启动盘制作、BIOS设置避坑到备份参数解析和恢复操作,涵盖了所有关键步骤和常见问题解决方案,帮助用户高效保护系统数据。

weixin_42116058的博客 641

VMD-CNN-BiLSTM-Attention预测模型 —— 数学模型介绍&完整实例代码

想解决电力负荷预测中的非线性、非平稳难题?这篇博客介绍了一种创新混合模型,结合变分模态分解(VMD)和CNN-BiLSTM-Attention深度学习架构,实现超高精度预测! ✨ 核心亮点: ✅ VMD分解:有效分离复杂负荷信号,提取关键频率特征 ✅ 混合深度学习:CNN捕捉局部模式 + BiLSTM学习长时序依赖 + 注意力机制聚焦关键时段 ✅ 端到端优化:从数据预处理(滑动窗口、归一化)到模型训练(MSE损失+Adam优化),完整流程公开! ✅ 工业级评估:提供MSE、MAE、MAPE、R²多指标验证

qq_42924330的博客 1653

android 系统启动该过程详解

android 系统启动该过程详解

Android framework 90

MATLAB自动驾驶(1)——预构建场景库

MATLAB自动驾驶(1)——预构建场景库

Ucicorn Gundam的博客 3265

Android 系统启动过程详解

原文:Android 系统启动过程详解 android 使用 linux 内核,一般运行在 ARM 体系架构上,android 设备启动的过程,应用层之下基本等同于linux, 从应用层第一个程序init开始有所区别,下面开始介绍。   step1, boot rom 主要作用是加载 boot loader 进入内存并执行,boot rom 一般固化在芯片上,设备启动加电自检后从固定

Imgloox的博客 1033

37.华为路由器:loopback(本地回环)接口的作用

本地环回接口(或地址),亦称回送地址(loopback address)。 此类接口是应用最为广泛的一种虚接口,几乎在每台路由器上都会使用。常见于如下用途: 1 作为一台路由器的管理地址 系统管理员完成网络规划之后,为了方便管理,会为每一台路由器创建一个loopback 接口,并在该接口上单独指定一个IP 地址作为管理地址 ,管理员会使用该地址对路由器远程登录(telnet ),该地址实际上起到了类似设备名称一类的功能。 但是通常每台路由器上存在众多接口和地址,为何不从当中随便挑选一个呢 ? 原因如下:由于

迷逝 3万+

化工设计软件:AutoCAD Plant 3D二次开发_(1).AutoCADPlant3D概述

AutoCAD Plant 3D 是一款专为化工行业设计的三维工厂设计和建模软件。它基于AutoCAD平台,提供了强大的三维建模功能和专业的化工设计工具,帮助工程师和设计师在工厂设计过程中提高效率和准确性。AutoCAD Plant 3D不仅能够创建详细的三维模型,还可以进行管道设计、设备布置、支架设计等复杂任务。通过上述案例,我们可以看出 AutoCAD Plant 3D 在化工厂设计中的强大功能和优势。该软件不仅提供了丰富的建模工具和专业的设计功能,还支持二次开发,使用户能够根据具体需求进行定制化操作。

kkchenjj的博客 1103

linux内核启动+Android系统启动过程详解

本文是《Android内核开发》系列的第六篇文章,前面的几篇文章介绍了Android内核开发相关的基础知识,包括:Android源码的下载、版本和分支介绍、编译和烧写等等,从本文起就要开始真正地进行Android内核的学习及实战了。 学习任何软硬件系统,研究系统启动过程都是一种非常有效地起步手段,搞Android内核开发也不例外。网上有很多文章对Android启动相关代码进行分析和走读,大...

simonlv123的专栏 1265

【嘉立创EDA】PCB 多层板如何交换内层,4层板交换板层

本文使用嘉立创EDA,描述如何在PCB设计时,如何交换各个板层,特别是4层板需要交换内层时,应该如何操作,以供有需要的读者参考。

l64481000的博客 2014

Android系统启动过程详解【转】

前言 一直想研究Android完整的启动过程,网上看了不少资料,也看了书上的一些说明,对这些观点有些怀疑,于是自己分析了系统启动的完整过程。从内核启动第一个用户程序init开始说起,直到Home应用的启动,每一步都有源代码展示。希望能解除读者对Android系统启动过程中的困惑,若有什么疑问,欢迎留言交流。本研究基于CM10.1源码,读者若能对照源代码查看效果会更好。 1) init启动ser...

weixin_34088598的博客 75

【2026年华为暑期实习/秋招(AI)-8月5日-第一题- 选择题】(题目+思路+Java&C++&Python解析+在线测试)

摘要: 本文包含20道选择题,涵盖深度学习、数值计算、概率统计、线性代数及机器学习等领域。重点考察了Softmax的数值稳定性实现(减去最大值)、视觉问答任务(图像+问题→答案)、分层强化学习的奖惩计算、欧氏距离与余弦相似度、反向传播梯度计算、SVD降维存储优化、贝叶斯概率推断、插值多项式等。此外,涉及逻辑回归评价指标(不含MSE)、端侧推理内存因素(中间激活)、集中趋势度量(均值)、Householder变换性质、早期停止正则化、梯度矩阵秩与优化、在线学习特性及大模型训练技巧(如学习率预热、梯度裁剪)等知

m0_73659489的博客 191

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【安卓开发系列 -- 系统分析】Framework -- Android 系统一般启动流程简介

【安卓开发系列 -- 系统开发】Framework -- init 解析 【1】Android 系统的整体启动流程 整体的启动流程图 【2】init 进程 【2.0】init 进程涉及的源文件路径 system\core\init\init.cpp 【2.1】init 进程职责 1. init 进程负责创建 Android 系统中的关键进程; 2. 提供属性服务 (property service) 管理 Android 系统中的属性; 参考与致谢 本博客为博主学习笔记,..

CopperSun 技术博客 679

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

上一篇: 迭代与增量的共性与区别
下一篇: 状态栏显示相关View Flag参数介绍
byszy
博客等级 码龄17年 42粉丝 36原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值