当前位置: 首页 > news >正文

【Android FrameWork (三)】- SystemServer

文章目录

  • 知识回顾
    • 启动第一个流程init
    • Zygote的流程
  • 前言
  • 源码分析
    • 1.system_server
    • 2.SystemServer.main
    • 3,startBootstrapServices
    • 4,startService
  • 拓展知识
    • LoadApk
    • context 对于Android context 大家是怎么理解的?
    • LocalServices.java: addServece方法中 ArrayMap和HashMap的区别?
    • AMS、PMS是谁启动的?他们都是独立的进程吗?
    • WatchDog 看门狗机制?
    • 简述system_server的启动
  • 总结


知识回顾

启动第一个流程init

1,挂载文件系统,创建文件目录 调用selinux_setup权限安全相关
2,初始化内存空间 初始化属性服务 创建Epoll 注册监听子进程重启异常操作等,对子进程进行线程守护
3,startPropertyServic 开启属性服务 进行监听
4,LoadBootScripts 加载init.rc文件 进行解析 调用do_class_start 文件开启service
5,Service::Start函数->fork子进程->并且执行app_process文件,开启了zygote

Zygote的流程

1,startVm函数注册jvm startReg函数注册jni环境唤起 Zygote.main
2,forkSystemServer
3,preload预加载class 系统资源
4,调用runSelectLoop函数循环等待客户端连接
5,有客户端的连接后调用processOneCommand()函数 fork进程,初始化进程,创建ProcessState初始化binder
6,根据请求的targetClass 执行Main函数

前言

Android系统在启动的时候有两个非常重要的进程,Zygote & system_server。SystemServer是系统用来启动service的入口,比如我们常用的 AMSWMSPMS等都是由它创建的。
SystemServer主要是创建SystemServiceManager,对系统服务进行创建、启动以及管理。


源码分析

1.system_server

Zygote启动之后会调用ZygoteInit.java的main函数,会执行forkSystemServer

 private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {……………………/* Hardcoded command line to start the system server *///准备 开启system_server的参数String args[] = {"--setuid=1000","--setgid=1000","--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010","--capabilities=" + capabilities + "," + capabilities,"--nice-name=system_server","--runtime-args","--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,"com.android.server.SystemServer",};ZygoteArguments parsedArgs = null;int pid;try {//把参数包装成ZygoteArgumentsparsedArgs = new ZygoteArguments(args);Zygote.applyDebuggerSystemProperty(parsedArgs);Zygote.applyInvokeWithSystemProperty(parsedArgs);boolean profileSystemServer = SystemProperties.getBoolean("dalvik.vm.profilesystemserver", false);if (profileSystemServer) {parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;}/* Request to fork the system server process */
//            fork出来system_server 还是调用到native层com_android_internal_os_Zygote_nativeForkSystemServerpid = Zygote.forkSystemServer(parsedArgs.mUid, parsedArgs.mGid,parsedArgs.mGids,parsedArgs.mRuntimeFlags,null,parsedArgs.mPermittedCapabilities,parsedArgs.mEffectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}/* For child process */if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//关闭掉ServerSocketzygoteServer.closeServerSocket();
//这里我们看到返回的是一个Runnable 就可以联想到Zygote中的MethodAndArgsCallerreturn handleSystemServerProcess(parsedArgs);}return null;}
//fork最终会调用到Native层
//com_android_internal_os_Zygote_nativeForkSystemServer
//。文件目录/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp。static jint com_android_internal_os_Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,jlong effective_capabilities) {std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),fds_to_ignore(fds_to_close);fds_to_close.push_back(gUsapPoolSocketFD);if (gUsapPoolEventFD != -1) {fds_to_close.push_back(gUsapPoolEventFD);fds_to_ignore.push_back(gUsapPoolEventFD);}//调用forkCommon函数,这个之前在Zygote中有跟踪过,这里就不跟了。调用fork并返回pid_tpid_t pid = ForkCommon(env, true,fds_to_close,fds_to_ignore);if (pid == 0) {SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,permitted_capabilities, effective_capabilities,MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,false, nullptr, nullptr);} else if (pid > 0) {ALOGI("System server process %d has been created", pid);gSystemServerPid = pid;int status;if (waitpid(pid, &status, WNOHANG) == pid) {//做一次安全检查ALOGE("System server process %d has died. Restarting Zygote!", pid);RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");}if (UsePerAppMemcg()) {if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {ALOGE("couldn't add process %d into system memcg group", pid);}}}return pid;
}
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {Os.umask(S_IRWXG | S_IRWXO);if (parsedArgs.mNiceName != null) {Process.setArgV0(parsedArgs.mNiceName);}final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");if (systemServerClasspath != null) {if (performSystemServerDexOpt(systemServerClasspath)) {sCachedSystemServerClassLoader = null;}boolean profileSystemServer = SystemProperties.getBoolean("dalvik.vm.profilesystemserver", false);if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {try {prepareSystemServerProfile(systemServerClasspath);} catch (Exception e) {Log.wtf(TAG, "Failed to set up system server profile", e);}}}if (parsedArgs.mInvokeWith != null) {//这里是NullString[] args = parsedArgs.mRemainingArgs;if (systemServerClasspath != null) {String[] amendedArgs = new String[args.length + 2];amendedArgs[0] = "-cp";amendedArgs[1] = systemServerClasspath;System.arraycopy(args, 0, amendedArgs, 2, args.length);args = amendedArgs;}WrapperInit.execApplication(parsedArgs.mInvokeWith,parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,VMRuntime.getCurrentInstructionSet(), null, args);throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");} else {createSystemServerClassLoader();//创建SystemServer的ClassLoaderClassLoader cl = sCachedSystemServerClassLoader;//将创建好的ClassLoader赋值给clif (cl != null) {Thread.currentThread().setContextClassLoader(cl);}//调用ZygoteInit.zygoteInit 和Zygote一样 创建ProcessState 打开binder 并调用RuntimeInit.applicationInit 返回startClass的Main函数的caller也 也就是执行com.android.server.SystemServer的main函数return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mRemainingArgs, cl);}}

2.SystemServer.main

main函数转头就掉了run函数,run函数中 创建了Looper、加载了android_server函数库、创建了SystemServiceManager(对服务进行创建、启动和管理)并且添加到LocalService(一个ArrayMap)中、startBootstrapServices(开启引导服务)、startCoreServices(开启核心服务)、startOtherServices(开启其他服务)、Looper开启。

public static void main(String[] args) {//转头就钓了run函数new SystemServer().run();
}private void run() {try {traceBeginAndSlog("InitBeforeStartServices");SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {Slog.w(TAG, "System clock is before 1970; setting to 1970.");SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);}String timezoneProperty = SystemProperties.get("persist.sys.timezone");if (timezoneProperty == null || timezoneProperty.isEmpty()) {Slog.w(TAG, "Timezone not set; setting to GMT.");SystemProperties.set("persist.sys.timezone", "GMT");}if (!SystemProperties.get("persist.sys.language").isEmpty()) {final String languageTag = Locale.getDefault().toLanguageTag();SystemProperties.set("persist.sys.locale", languageTag);SystemProperties.set("persist.sys.language", "");SystemProperties.set("persist.sys.country", "");SystemProperties.set("persist.sys.localevar", "");}Binder.setWarnOnBlocking(true);PackageItemInfo.forceSafeLabels();SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;SQLiteCompatibilityWalFlags.init(null);Slog.i(TAG, "Entered the Android system server!");int uptimeMillis = (int) SystemClock.elapsedRealtime();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);if (!mRuntimeRestart) {MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);}SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());VMRuntime.getRuntime().clearGrowthLimit();VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);Build.ensureFingerprintProperty();Environment.setUserRequired(true);BaseBundle.setShouldDefuse(true);Parcel.setStackTraceParceling(true);BinderInternal.disableBackgroundScheduling(true);BinderInternal.setMaxThreads(sMaxBinderThreads);android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);android.os.Process.setCanSelfBackground(false);Looper.prepareMainLooper();//创建消息的LooperLooper.getMainLooper().setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);//加载函数库 libandroid_servers.soSystem.loadLibrary("android_servers");if (Build.IS_DEBUGGABLE) {initZygoteChildHeapProfiling();}performPendingShutdown();// Initialize the system context.createSystemContext();//创建系统Context// Create the system service manager. 创建ServiceManagermSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);//将SystemServiceManager添加到LocalServices中 LocalService 内部其实就是一个ArrayMapLocalServices.addService(SystemServiceManager.class, mSystemServiceManager);// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.get();} finally {traceEnd();  // InitBeforeStartServices}// Start services. 开启服务try {traceBeginAndSlog("StartServices");startBootstrapServices();//开启引导服务startCoreServices();//开启核心服务startOtherServices();//开启其他服务SystemServerInitThreadPool.shutdown();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {traceEnd();}StrictMode.initVmDefaults(null);if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {int uptimeMillis = (int) SystemClock.elapsedRealtime();MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);final int MAX_UPTIME_MILLIS = 60 * 1000;if (uptimeMillis > MAX_UPTIME_MILLIS) {Slog.wtf(SYSTEM_SERVER_TIMING_TAG,"SystemServer init took too long. uptimeMillis=" + uptimeMillis);}}if (!VMRuntime.hasBootImageSpaces()) {Slog.wtf(TAG, "Runtime is not running with a boot image!");}// Loop forever.//loop启动Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}

3,startBootstrapServices

开启了看门狗(用于监控system_server,一旦出现问题会杀死SystemServer,SystemServer撕掉会告诉Zygote Zygote接收到之后会杀死自己 然后告诉init init又会重启Zygote并且激活对应的onRestart)以及相当多的服务,其中有我们熟悉的Installer、ActivityTaskManagerService、ActivityManagerService、PowerManagerService、PackageManagerService等等,基本上就是通过startService方法

private void startBootstrapServices() {traceBeginAndSlog("StartWatchdog");final Watchdog watchdog = Watchdog.getInstance();watchdog.start();//开启看门狗traceEnd();Slog.i(TAG, "Reading configuration...");final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";traceBeginAndSlog(TAG_SYSTEM_CONFIG);SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);traceEnd();traceBeginAndSlog("StartInstaller");//开启Installer服务Installer installer = mSystemServiceManager.startService(Installer.class);traceEnd();traceBeginAndSlog("DeviceIdentifiersPolicyService");//开启设备标识符访问策略服务mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);traceEnd();traceBeginAndSlog("UriGrantsManagerService");mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);traceEnd();// Activity manager runs the show.traceBeginAndSlog("StartActivityManager");//启动ActivityTaskManagerService、mActivityManagerService服务并关联systemServiceManager以及installerActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);mWindowManagerGlobalLock = atm.getGlobalLock();traceEnd();// Power manager needs to be started early because other services need it.// Native daemons may be watching for it to be registered so it must be ready// to handle incoming binder calls immediately (including being able to verify// the permissions for those calls).traceBeginAndSlog("StartPowerManager");//开启PowerManagerService服务mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);traceEnd();traceBeginAndSlog("StartThermalManager");mSystemServiceManager.startService(ThermalManagerService.class);traceEnd();// Now that the power manager has been started, let the activity manager// initialize power management features.traceBeginAndSlog("InitPowerManagement");mActivityManagerService.initPowerManagement();traceEnd();// Bring up recovery system in case a rescue party needs a reboottraceBeginAndSlog("StartRecoverySystemService");mSystemServiceManager.startService(RecoverySystemService.class);traceEnd();// Now that we have the bare essentials of the OS up and running, take// note that we just booted, which might send out a rescue party if// we're stuck in a runtime restart loop.RescueParty.noteBoot(mSystemContext);// Manages LEDs and display backlight so we need it to bring up the display.traceBeginAndSlog("StartLightsService");mSystemServiceManager.startService(LightsService.class);traceEnd();traceBeginAndSlog("StartSidekickService");// Package manager isn't started yet; need to use SysProp not hardware featureif (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);}traceEnd();// Display manager is needed to provide display metrics before package manager// starts up.traceBeginAndSlog("StartDisplayManager");mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);traceEnd();// We need the default display before we can initialize the package manager.traceBeginAndSlog("WaitForDisplay");mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);traceEnd();// Only run "core" apps if we're encrypting the device.String cryptState = VoldProperties.decrypt().orElse("");if (ENCRYPTING_STATE.equals(cryptState)) {Slog.w(TAG, "Detected encryption in progress - only parsing core apps");mOnlyCore = true;} else if (ENCRYPTED_STATE.equals(cryptState)) {Slog.w(TAG, "Device encrypted - only parsing core apps");mOnlyCore = true;}// Start the package manager.if (!mRuntimeRestart) {MetricsLogger.histogram(null, "boot_package_manager_init_start",(int) SystemClock.elapsedRealtime());}traceBeginAndSlog("StartPackageManagerService");try {Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");//创建PackageManagerService服务mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);} finally {Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");}mFirstBoot = mPackageManagerService.isFirstBoot();mPackageManager = mSystemContext.getPackageManager();traceEnd();if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {MetricsLogger.histogram(null, "boot_package_manager_init_ready",(int) SystemClock.elapsedRealtime());}// Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename// A/B artifacts after boot, before anything else might touch/need them.// Note: this isn't needed during decryption (we don't have /data anyways).if (!mOnlyCore) {boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",false);if (!disableOtaDexopt) {traceBeginAndSlog("StartOtaDexOptService");try {Watchdog.getInstance().pauseWatchingCurrentThread("moveab");OtaDexoptService.main(mSystemContext, mPackageManagerService);} catch (Throwable e) {reportWtf("starting OtaDexOptService", e);} finally {Watchdog.getInstance().resumeWatchingCurrentThread("moveab");traceEnd();}}}traceBeginAndSlog("StartUserManagerService");mSystemServiceManager.startService(UserManagerService.LifeCycle.class);traceEnd();// Initialize attribute cache used to cache resources from packages.traceBeginAndSlog("InitAttributerCache");AttributeCache.init(mSystemContext);traceEnd();// Set up the Application instance for the system process and get started.traceBeginAndSlog("SetSystemProcess");mActivityManagerService.setSystemProcess();traceEnd();// Complete the watchdog setup with an ActivityManager instance and listen for reboots// Do this only after the ActivityManagerService is properly started as a system processtraceBeginAndSlog("InitWatchdog");watchdog.init(mSystemContext, mActivityManagerService);traceEnd();// DisplayManagerService needs to setup android.display scheduling related policies// since setSystemProcess() would have overridden policies due to setProcessGroupmDisplayManagerService.setupSchedulerPolicies();// Manages Overlay packagestraceBeginAndSlog("StartOverlayManagerService");mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));traceEnd();traceBeginAndSlog("StartSensorPrivacyService");mSystemServiceManager.startService(new SensorPrivacyService(mSystemContext));traceEnd();if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {// DisplayManager needs the overlay immediately.mActivityManagerService.updateSystemUiContext();LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();}// The sensor service needs access to package manager service, app ops// service, and permissions service, therefore we start it after them.// Start sensor service in a separate thread. Completion should be checked// before using it.mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {TimingsTraceLog traceLog = new TimingsTraceLog(SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);traceLog.traceBegin(START_SENSOR_SERVICE);startSensorService();traceLog.traceEnd();}, START_SENSOR_SERVICE);
}

4,startService

public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();Slog.i(TAG, "Starting " + name);Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name+ ": service must extend " + SystemService.class.getName());}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {throw new RuntimeException("Failed to create service " + name+ ": service could not be instantiated", ex);} catch (IllegalAccessException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (NoSuchMethodException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (InvocationTargetException ex) {throw new RuntimeException("Failed to create service " + name+ ": service constructor threw an exception", ex);}//通过反射创建传递过来的Service对象,调用startServicestartService(service);return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}
}public void startService(@NonNull final SystemService service) {//将service添加到mServices中去mServices.add(service);long time = SystemClock.elapsedRealtime();try {//调用service的onStart函数启动对应的serviceservice.onStart();} catch (RuntimeException ex) {throw new RuntimeException("Failed to start service " + service.getClass().getName()+ ": onStart threw an exception", ex);}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");}

拓展知识

LoadApk

LoadApk:理解为apk文件加载到内存的一个java对象 framework-res.apk

context 对于Android context 大家是怎么理解的?

LocalServices.java: addServece方法中 ArrayMap和HashMap的区别?

ArrayMap k,v k是int类型的包装,k是从小到大依次排列。时间复杂度可以是存的是 O(1). 取的过程就是log(n map.size). put和 get
HashMap <k(Object),v > 时间复杂度 put和 get O(1). K是一个复合类型,计算hash值 假如现在的k是String类型,那么就需要遍历当前字符串 计算当前“jijs”字符串的hash值存储到对应的位置上去 对应时间复杂度O(k) k复杂增长
ArrayList ?

AMS、PMS是谁启动的?他们都是独立的进程吗?

他们是由system_server启动,不是独立进程,他们都运行在system_server进程中。

WatchDog 看门狗机制?

原理:是一个单例模式,有一个handlerChecker集合,根据handler进行监控,监控所有的service 假如长时间未响应,AMS handler sendMessage(MQ)时间戳

简述system_server的启动

Zygote调用forkSystemServer来创建system_server进程,调用到Java层SystemServer.java.Main,创建SystemServer的ActivityThread 创建framewok-res.apk的Application调用onCreate,调用startBootstrapServices、startCoreServices、startOtherServices创建各种各样的Service(AMS、PMS等),并开启开门狗检测服务和线程,如果出现问题就会杀死system_server,system_server死亡之后会通知Zygote,
Zygote会杀死自己 通知init, init有线程守护,会重启Zygote 并执行对应的onRestart服务。

总结

1.system_server是在Zygote启动的时候fork出来的子进程,调用的是ZygoteInit.forkSystemServer,最终返回MethodAndArgsCaller包装的是com.android.server.SystemServer.Main。

2.SystemServer.Main函数直接调用了run函数,在run函数中调用了createSystemContext通过ActivityThread.systemMain创建了ActivityThread,设置了mSystemContext并且调用ActivityThread.attach 通过反射创建Application 执行onCreate函数.这里创建的app是framewok-res.apk,是给系统使用的 比如系统的对话框。将mSystemServiceManager添加到LocalService的mService(ArrayMap)中去接着调用startBootstrapServices、startCoreServices、startOtherServices开启了非常多的服务Installer、ATMS、AMS、PMS等。把他们添加到SystemServiceManager的mServices(ArrayList)中去。
在这里插入图片描述

相关文章:

【Android FrameWork (三)】- SystemServer

文章目录 知识回顾启动第一个流程initZygote的流程 前言源码分析1.system_server2.SystemServer.main3,startBootstrapServices4,startService 拓展知识LoadApkcontext 对于Android context 大家是怎么理解的&#xff1f;LocalServices.java: addServece方法中 ArrayMap和HashM…...

Docker容器部署及基本使用

文章目录 一、环境初始化配置二、安装Docker三、优化配置四、基础命令 一、环境初始化配置 1、关闭防火墙 systemctl stop firewalld systemctl disable firewalldsetenforce 0sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config sed -i s/SELINUXenforcing/S…...

【机智云物联网低功耗转接板】+模拟MCU快速上手

GE211是机智云自研的定制化转接板&#xff0c;使用 ESP32-C3-WROOM-02 通讯模块&#xff0c;适用于白色智能家电等设备应用。 转接板已经烧录了机智云连云的最新GAgent固件&#xff0c;所以不需要烧写任何软件就可以快速上手使用。 GE211板卡带有一个串口&#xff0c;一般是把这…...

ai免费写作在线平台-ai免费伪原创文章生成器软件

ai伪原创能检测出来吗 人工智能技术可以检测伪原创&#xff0c;但是不是所有的伪原创都可以被检测出来。 现在有许多自然语言处理&#xff08;NLP&#xff09;算法和技术可以用来检测伪原创内容&#xff0c;例如文本相似度比较算法&#xff0c;语气分析算法等。这些算法可以检…...

Web自动化测试简介及web自动化测试实战交教程

一、认识web自动化测试 1.什么是自动化测试&#xff1f; 自动化测试的概念: 软件自动化测试就是通过测试工具或者其他手段&#xff0c;按照测试人员的预定计划对软件产品进行自动化测试&#xff0c;他是软件测试的一个重要组成部分&#xff0c;能够完成许多手工测试无法完成或…...

基于单片机的家庭应急电源设计

基于单片机的家庭应急电源 摘 要 本设计基于STC89C52单片机设计得应急电源&#xff0c;以应急电源为研究对象&#xff0c;单片机设计为控制集成IC&#xff0c;ADC为模数转换控制模块&#xff0c;无源蜂鸣器作为报警电路。系统分为单片机设计最小系统&#xff0c;AD转换控制模…...

线程七大状态

线程生命周期&#xff08;七大状态&#xff09; 新建状态&#xff08;New&#xff09;&#xff1a;当Java线程被创建时&#xff0c;它处于新建状态。此时&#xff0c;线程对象已被创建&#xff0c;但尚未启动。在这个状态下&#xff0c;线程并没有开始执行任何代码&#xff0c;…...

Linux第一章

文章目录 前言一、操作系统概述二、Linux初识1.Linux系统的诞生2.Linux系统内核3.Linux发行版 三、虚拟机介绍四、安装vmware workStation1.VMware WorStation软件2.安装 五、vm安装linux六、远程连接Linux系统1.图形化、命令行2.为什么使用命令行操作linux3.使用FinalShell软件…...

Microsoft Defender for Identity部署方案

目录 前言 一、重要组件 二、部署步骤 1、准备 Azure 订阅 2、配置 Microsoft Defender for Identity 门户...

超越YOLOv8,飞桨推出精度最高的实时检测器RT-DETR!

‍‍ 众所周知&#xff0c;实时目标检测( Real-Time Object Detection )一直由 YOLO 系列模型主导。 飞桨在去年 3 月份推出了高精度通用目标检测模型 PP-YOLOE &#xff0c;同年在 PP-YOLOE 的基础上提出了 PP-YOLOE 。后者在训练收敛速度、下游任务泛化能力以及高性能部署能力…...

基于Docker安装Redis【保姆级教程、内含图解】

Redis官网&#xff1a;Redis Redis中文官网&#xff1a;CRUG网站 两者选其一即可&#xff0c;建议使用 Redis官网&#xff1a;Redis 学习任何框架和技术&#xff0c;一定要参考相应的官网学习&#xff0c;一定要参考官网学习&#xff01;&#xff01;&#xff01; 目录 一、拉取…...

电子表格软件与一站式BI的区别

看完本节内容&#xff0c;相信您能够了解到电子表格软件&#xff08;代号电子表格软件&#xff09;与「一站式 BI」的主要区别。所谓一站式BI在官网上的名称就是Smartbi V10.5&#xff0c;代号就是Smartbi一直在使用insight。 这两个产品都属于商业智能BI软件的品类&#xff0…...

SpringCache

一、介绍 Spring Cache是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单地加一个注解&#xff0c;就能实现缓存功能&#xff0c;大大简化我们在业务中操作缓存的代码。 Spring Cache只是提供了一层抽象&#xff0c;底层可以切换不同的cache实现。具体就…...

Android Framework—Service

介绍 Service是一种可以在后台执行长时间运行操作而不提供界面的应用组件。服务可以由其他应用组件启动&#xff0c;而且即使用户切换到其他应用&#xff0c;服务仍将在后台继续运行。此外&#xff0c;组件可以通过绑定到服务与之进行交互&#xff0c;甚至是执行进程之间的通信…...

leetcode (重排数组使得)连续子数组的权值和最小

题目描述&#xff1a;请重新排列某个仅包含2和3的数组&#xff0c;使得数组的所有连续子数组权值之和最小数组的权值定义为,数组中所有元素之积的因子个数&#xff0c;例如&#xff1a;rank([2,3])4 x p 1 c 1 p 2 c 2 p 3 c 3 ⋅ ⋅ ⋅ p k c k r a n k ( c 1 1 ) ( c …...

JSP计算机等级考试查询系统(源代码+论文+答辩PPT)

第一章 引言 计算机等级考试查询系统是有其开发的必要性的&#xff0c;它的应用将大大节省了学校的人力资源&#xff0c;从而从人工劳动中解脱出来。我们这次开发的软件系统一共包括了三个部分&#xff1a;等级考试的报名系统、查询系统和管理系统。其中管理系统是另外两部分…...

python 基础系列篇:七、以函数方式编写一个数字华容道

python 基础系列篇&#xff1a;七、以函数方式编写一个数字华容道 数字华容道游戏分析开始编写完整代码代码解说定义方法的规律 小结 数字华容道 嗯&#xff0c;就是一个简单的益智游戏&#xff0c;把数字按照特定规律排列&#xff0c;并比矩阵少一个格&#xff0c;用来进行移…...

2023年前端面试题

1.position都有哪些属性 2.1px等于多少rem&#xff0c;rem根据根元素的大小&#xff0c;根元素是谁 3.Es6操作数组的方法 4.防抖和节流以及应用场景 5.Vue和ajax最大的区别是什么&#xff08;Vue和ajax怎么操作dom的&#xff0c;vue虚拟dom&#xff09; 6.js数据类型有哪些&…...

快速入门量化交易

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注"慕课网"&#xff01; 原作者&#xff1a;袁霄|慕课网讲师 近来“量化交易”这个词听得越来越频繁&#xff0c;多数人对量化交易的第一印象是“高大上的技术”…...

Mongodb oplog

在MongoDB复制集中,oplog信息存储在oplog.rs集合中。 oplog.rs集合是一个固定大小的集合(capped collection),它位于local数据库中。 当我们在源MongoDB实例上启用了复制(replication)功能,MongoDB会自动在local数据库中创建oplog.rs集合。此后,所有在该实例上的写操作都会生…...

python基础篇: python字符串方法都有哪些?你知道多少?

❝ Python提供了丰富的字符串处理方法&#xff0c;可以方便地对字符串进行操作、处理和转换。在本文中&#xff0c;我们将介绍Python中常用的字符串方法。 ❞ python中字符串内置方法很多&#xff0c;可以通过dir()方式查看具体有哪些方法&#xff0c;下表是python字符串的全部…...

chmod 命令 (chmod 0660)

chmod的作用: 用于设置文件所有者和文件关联组的命令,就是控制用户的权限命令 注意事项: chown 需要超级用户 root 的权限才能执行此命令。 自己常用chmod 命令是 chmod 777 * 给所有文件权限 chmod 777 文件名 给单独文件权限 这个777 是怎么来的, 或者chmod 0660 这…...

Qt应用开发常用功能

Qt判断当前操作系统&#xff1f; #ifdef Q_OS_MAC //mac ... #endif#ifdef Q_OS_LINUX //linux ... #endif#ifdef Q_OS_WIN32 //win ... #endif#ifdef __arm__ //arm ... #endifQt实现应用程序关闭和重启&#xff1f; //关机按钮-点击槽函数 void SystemD::on_shutdownButton…...

麻了,部门新来的00后给我卷崩溃了...

今天上班开早会就是新人见面仪式&#xff0c;听说来了个很厉害的大佬&#xff0c;年纪还不大&#xff0c;是上家公司离职过来的&#xff0c;薪资已经达到中高等水平&#xff0c;很多人都好奇不已&#xff0c;能拿到这个薪资应该人不简单&#xff0c;果然&#xff0c;自我介绍的…...

代码随想录算法训练营第56天|583. 两个字符串的删除操作,72. 编辑距离

代码随想录算法训练营第56天|583. 两个字符串的删除操作&#xff0c;72. 编辑距离 583. 两个字符串的删除操作72. 编辑距离 583. 两个字符串的删除操作 题目链接&#xff1a;583. 两个字符串的删除操作&#xff0c;难度&#xff1a;中等 【实现代码】 class Solution { publi…...

【嵌入式笔/面试】嵌入式软件基础题和真题总结——操作系统

在学习的时候找到几个十分好的工程和个人博客&#xff0c;先码一下&#xff0c;内容都摘自其中&#xff0c;有些重难点做了补充&#xff01; 才鲸 / 嵌入式软件笔试题汇总 嵌入式与Linux那些事 阿秀的学习笔记 小林coding 百问网linux 嵌入式软件面试合集 2022年春招实习十四面…...

2023浙江省赛“信息安全管理与评估“--Web渗透测试(高职组)

2022全国职业技能大赛“信息安全管理与评估”(高职组)任务书 2022全国职业技能大赛“信息安全管理与评估”任务书第一阶段竞赛项目试题第二阶段竞赛项目试题第三阶段竞赛项目试题任务2:Web渗透测试2022全国职业技能大赛“信息安全管理与评估”任务书 第一阶段竞赛项目试题 …...

垃圾收集器面试总结(二)

G1 收集器 G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。 被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征。它具备以下特点&#xff1a; 并行与并发&am…...

语音交友app开发中的用户积分系统

引言 在当今数字时代&#xff0c;语音交友app已成为一种流行的社交工具。它们给用户提供了一个平台&#xff0c;在这里他们可以结交新朋友&#xff0c;分享他们的生活和信仰&#xff0c;并建立深厚的人际关系。然而&#xff0c;市场上存在大量的语音交友app&#xff0c;这使得…...

Nature:惊人的突破!科学家们成功破译人类嗅觉感应机制的奥秘!

加州大学旧金山分校&#xff08;UCSF&#xff09;的科学家们创造了第一张关于气味分子如何激活人类气味受体的分子水平的3D图片&#xff0c;这是破译嗅觉的关键一步&#xff0c;该成果打破了长期以来研究人员对嗅觉理解的僵局。 该研究成果于2023年3月15日发表在《Nature》&…...