Android开发学习—手机开机启动的AMS流程

news2025/7/27 17:09:52

前言

AMS是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要。

客户端使用ActivityManager类。由于AMS是系统核心服务,很多API不能开放供客户端使用,所以设计者没有让ActivityManager直接加入AMS家族。在ActivityManager类内部通过调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信。

启动流程

在Android系统启动流程中中我们提到过,AMS是在system_service中启动的,

//frameworks/base/services/java/corri/android/server/SystemServer.java
 
//该方法主要启动服务 ActivityManagerService,PowerManagerService,LightsService,DisplayManagerService,PackageManagerService,UserManagerService。
//设置 ActivityManagerService,启动传感器服务。
startBootstrapServices(); // 启动引导服务
 
//该方法主要
//启动服务 BatteryService 用于统计电池电量,需要 LightService。
//启动服务 UsageStatsService,用于统计应用使用情况。
//启动服务 WebViewUpdateService。
startCoreServices(); // 启动核心服务
 
//该方法主要启动服务 InputManagerService,WindowManagerService。
//等待 ServiceManager,SurfaceFlinger启动完成,然后显示启动界面。
//启动服务 StatusBarManagerService,
//准备好 window, power, package, display 服务:
//  - WindowManagerService.systemReady()
//  - PowerManagerService.systemReady()
//  - PackageManagerService.systemReady()
//  - DisplayManagerService.systemReady()
startOtherServices(); // 启动其他服务

在启动核心服务功能中,会进行AMS的启动。

//frameworks/base/services/java/corri/android/server/SystemServer.java
private void startBootstrapServices() {
   ...
//这里会将ATMS注册到ServiceManager中,然后调用ATMS的start方法。
ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();
//重点方法1。 注册AMS服务,并返回对应的对象信息
mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//设置app安装器
mActivityManagerService.setInstaller(installer);
...
//重点方法2。 向ServiceManager中注册Binder服务
mActivityManagerService.setSystemProcess();
}

这里我们只截取了AMS的启动代码。

这里会通过startService方法来进行AMS的注册和启动过程。我们看一下具体的ActivityManagerService中的startService方法

startService

// 
    public static ActivityManagerService startService(SystemServiceManager ssm, ActivityTaskManagerService atm) {
  sAtm = atm;
  //调用SM的startService方法。创建AMS实例,并启动AMS
  return ssm.startService(ActivityManagerService.Lifecycle.class).getService();
 }

我们在ServiceManager的工作原理中讲解过,systemServiceManager.startService方法会将对应的服务注册到ServiceManager中,然后再调用start方法。

//frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
        public SystemService startService(String className) {
 final Class<SystemService> serviceClass;
 serviceClass = (Class<SystemService>)Class.forName(className);
 return startService(serviceClass);
 }
 
 @SuppressWarnings("unchecked")
 public <T extends SystemService> T startService(Class<T> serviceClass) {
 try {
  final String name = serviceClass.getName();
  final T service;
  try {
  //反射构造函数
  Constructor<T> constructor = serviceClass.getConstructor(Context.class);
  //创建服务
  service = constructor.newInstance(mContext);
  ...
  //启动服务
  startService(service);
  return service;
 } finally {
  Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 }
 }
 
 public void startService(@NonNull final SystemService service) {
 // Register it.
 //注册到ServiceManager列表中
 mServices.add(service);
 //调用服务对应的onStart方法
 service.onStart();
 }

在启动AMS的时候传入的参数是:ActivityManagerService.Lifecycle.class。所以这里实际上会调用ActivityManagerService.Lifecycle 的构造方法,然后调用它的onStart方法

public static final class Lifecycle extends SystemService {
private final ActivityTaskManagerService mService;
public Lifecycle(Context context) {
 super(context);
 //创建AMS对象
 mService = new ActivityManagerService(context, sAtm);
}
@Override
public void onStart() {
 //调用AMS的start方法
 mService.start();
}
 
public ActivityManagerService getService() {
 //返回了AMS实例
 return mService;
}
}

在Lifecycle对象的创建过程中,会创建AMS对象,然后通过start()方法进行了启动。

AMS的创建

对于AMS对象的创建是通过构造函数来创建的。

//构造方法,
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
//获取系统的ActivityThread
mSystemThread = ActivityThread.currentActivityThread();
//创建一个ServiceThread用来处理AMS接收到的命令
mHandlerThread = new ServiceThread(TAG,THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
mUiHandler = mInjector.getUiHandler(this);
//低内存监控
mLowMemDetector = new LowMemDetector(this);
//初始化广播队列。这里包含了前台广播,后台广播等
mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", foreConstants, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", backConstants, true);
mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, "offload", offloadConstants, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;
mBroadcastQueues[2] = mOffloadBroadcastQueue;
//用于保存注册的Service
mServices = new ActiveServices(this);
//map,用于保存注册的ContentProvider
mProviderMap = new ProviderMap(this);
mPackageWatchdog = PackageWatchdog.getInstance(mUiContext);
mAppErrors = new AppErrors(mUiContext, this, mPackageWatchdog);
 
//创建 /data/system目录
final File systemDir = SystemServiceManager.ensureSystemDir();
//创建进程统计服务,保存在/data/system/proccstats目录中。
mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
//赋值ATM,并进行初始化
mActivityTaskManager = atm;
mActivityTaskManager.initialize(mIntentFirewall, mPendingIntentController, DisplayThread.get().getLooper());
//CPU追踪器进程
mProcessCpuThread = new Thread("CpuTracker") {
 @Override
 public void run() {
 ...
 }
};
 
}

在AMS的构造函数中进行了一些初始化的东西:比如说启动CPU监控、启动进程统计服务、启动低内存监控、初始化Service和ContentProvider对应的保存类等等。

start()

当AMS类创建完成之后,会调用start()方法。

private void start() {
    //移除所有的进程组
removeAllProcessGroups();
//启动CpuTracker线程
mProcessCpuThread.start();
//启动电池统计服务,能够统计具体的应用的电池消耗,从而来进行一定的电量统计
mBatteryStatsService.publish();
//创建LocalService,并添加到LocalServices列表中
LocalServices.addService(ActivityManagerInternal.class, new LocalService());
mActivityTaskManager.onActivityManagerInternalAdded();
mUgmInternal.onActivityManagerInternalAdded();
mPendingIntentController.onActivityManagerInternalAdded();
}

在start方法中,会将在构造函数中创建的一些线程进行启动。

setSystemProcess

在创建并启动完成之后,会通过setSystemProcess方法来向ServiceManager中注册一些系统相关的服务。

public void setSystemProcess() {
try {
   //注册ActivityService服务
 ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
  DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
 //注册进程状态服务
 ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
 //注册内存Binder
 ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_HIGH);
 //注册图像Binder
 ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
 //注册SQLite DB binder
 ServiceManager.addService("dbinfo", new DbBinder(this));
 if (MONITOR_CPU_USAGE) {
   //注册CPU使用情况的Binder
 ServiceManager.addService("cpuinfo", new CpuBinder(this),/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
 }
 //注册权限控制Binder
 ServiceManager.addService("permission", new PermissionController(this));
 //注册进程管理Binder
 ServiceManager.addService("processinfo", new ProcessInfoService(this));
 //获取“android”应用的ApplicationInfo,并装载到mSystemThread
 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo("android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
 mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
 //创建ProcessRecord维护进程的相关信息
 synchronized (this) {
 ProcessRecord app = mProcessList.newProcessRecordLocked(info, info.processName,...);
 app.setPersistent(true);
 app.pid = MY_PID;
 app.getWindowProcessController().setPid(MY_PID);
 app.maxAdj = ProcessList.SYSTEM_ADJ;
 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
 mPidsSelfLocked.put(app);
 mProcessList.updateLruProcessLocked(app, false, null);
 updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
 }
} catch (PackageManager.NameNotFoundException e) {
 throw new RuntimeException(
  "Unable to find android system package", e);
}
}

在这个方法中会设置一些系统进程,主要功能为:

  • 注册一些服务:activity、procstats、meminfo、gfxinfo、dbinfo、cpuinfo、permission、processinfo等。
  • 获取包名为“android”的应用的ApplicationInfo对象,并将该ApplicationInfo信息安装设置到SystemThread(系统进程主线程)。即可以理解,系统也是一个特殊的应用。
  • 创建ProcessRecord维护进程的相关信息,这里MY_PID即为SystemServer进程ID。
  • 启动 检测应用运行和交互。

后续

当AMS创建并启动之后,会有一系列的后续的工作需要处理。这些操作都是在startOtherServices()中去调用的

private void startOtherServices() {
 //注册系统的ContentProvider信息
 mActivityManagerService.installSystemProviders();
 
 mActivityManagerService.setWindowManager(wm);
   mActivityManagerService.systemReady(() -> {
 ......//goingCallback
 }, BOOT_TIMINGS_TRACE_LOG);
}

这里的主要功能是:

  • 关键服务继续进行初始化
  • 已经启动的进程,如果没有FLAG_PERSISTENT标志位,则会被kill掉
  • 运行goingCallBack
  • 启动launcher的Activity,即桌面应用。

这里继续跟踪一下goingCallBack的具体执行内容。

goingCallBack

mActivityManagerService.systemReady(() -> {
 try {
 //启动NativeCrash的监测
 mActivityManagerService.startObservingNativeCrashes();
 } catch (Throwable e) {
 reportWtf("observing native crashes", e);
 }
 if (!mOnlyCore && mWebViewUpdateService != null) {
 webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
  //启动WebView相关
  mWebViewUpdateService.prepareWebViewInSystemServer();
 }, WEBVIEW_PREPARATION);
 }
 
 try {
 //启动systemUI
 startSystemUi(context, windowManagerF);
 } catch (Throwable e) {
 reportWtf("starting System UI", e);
 }
 ...
}

在这个里面会继续进行一些初始化的工作:

  • 启动NativeCrash监测
  • 启动WebView相关服务
  • 启动SystemUI

startHomeOnAllDisplays

该功能主要是进行桌面程序的启动,和AMS的启动流程关联不大,在这里不再详细进行解析。

AMS启动流程源码分析

1.AMS由SystemServer的ServerThread线程创建,代码如下:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

由以上代码分析可得:

AMS的创建是通过ActivityManagerService.java里面的Lifecycle类创建出来的。该LifeCycle的代码如下:

这个其实很好理解啦,就相当于AMS的生命周期。在后面的源码分析中我们会经常看到这个类,没什么好说的,就相当于一个服务的生命周期,从创建到销毁的整个过程。

我们去看一下AMS的构造方法里面有些什么东西,代码如下:

  1     public ActivityManagerService(Context systemContext) {
  2         LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
  3         mInjector = new Injector();
  4         mContext = systemContext;
  5 
  6         mFactoryTest = FactoryTest.getMode();
  7         mSystemThread = ActivityThread.currentActivityThread();
  8         mUiContext = mSystemThread.getSystemUiContext();
  9 
 10         Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
 11 
 12         mPermissionReviewRequired = mContext.getResources().getBoolean(
 13                 com.android.internal.R.bool.config_permissionReviewRequired);
 14 
 15         mHandlerThread = new ServiceThread(TAG,
 16                 THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
 17         mHandlerThread.start();
 18         mHandler = new MainHandler(mHandlerThread.getLooper());
 19         mUiHandler = mInjector.getUiHandler(this);
 20 
 21         mConstants = new ActivityManagerConstants(this, mHandler);
 22 
 23         /* static; one-time init here */
 24         if (sKillHandler == null) {
 25             sKillThread = new ServiceThread(TAG + ":kill",
 26                     THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
 27             sKillThread.start();
 28             sKillHandler = new KillHandler(sKillThread.getLooper());
 29         }
 30 
 31         mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
 32                 "foreground", BROADCAST_FG_TIMEOUT, false);
 33         mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
 34                 "background", BROADCAST_BG_TIMEOUT, true);
 35         mBroadcastQueues[0] = mFgBroadcastQueue;
 36         mBroadcastQueues[1] = mBgBroadcastQueue;
 37 
 38         mServices = new ActiveServices(this);
 39         mProviderMap = new ProviderMap(this);
 40         mAppErrors = new AppErrors(mUiContext, this);
 41 
 42         // TODO: Move creation of battery stats service outside of activity manager service.
 43         File dataDir = Environment.getDataDirectory();
 44         File systemDir = new File(dataDir, "system");
 45         systemDir.mkdirs();
 46         mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
 47         mBatteryStatsService.getActiveStatistics().readLocked();
 48         mBatteryStatsService.scheduleWriteToDisk();
 49         mOnBattery = DEBUG_POWER ? true
 50                 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
 51         mBatteryStatsService.getActiveStatistics().setCallback(this);
 52 
 53         mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
 54 
 55         mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);
 56         mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null,
 57                 new IAppOpsCallback.Stub() {
 58                     @Override public void opChanged(int op, int uid, String packageName) {
 59                         if (op == AppOpsManager.OP_RUN_IN_BACKGROUND && packageName != null) {
 60                             if (mAppOpsService.checkOperation(op, uid, packageName)
 61                                     != AppOpsManager.MODE_ALLOWED) {
 62                                 runInBackgroundDisabled(uid);
 63                             }
 64                         }
 65                     }
 66                 });
 67 
 68         mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
 69 
 70         mUserController = new UserController(this);
 71 
 72         mVrController = new VrController(this);
 73 
 74         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
 75             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 76 
 77         if (SystemProperties.getInt("sys.use_fifo_ui", 0) != 0) {
 78             mUseFifoUiScheduling = true;
 79         }
 80 
 81         mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
 82         mTempConfig.setToDefaults();
 83         mTempConfig.setLocales(LocaleList.getDefault());
 84         mConfigurationSeq = mTempConfig.seq = 1;
 85         mStackSupervisor = createStackSupervisor();
 86         mStackSupervisor.onConfigurationChanged(mTempConfig);
 87         mKeyguardController = mStackSupervisor.mKeyguardController;
 88         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
 89         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
 90         mTaskChangeNotificationController =
 91                 new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
 92         mActivityStarter = new ActivityStarter(this, mStackSupervisor);
 93         mRecentTasks = new RecentTasks(this, mStackSupervisor);
 94 
 95         mProcessCpuThread = new Thread("CpuTracker") {
 96             @Override
 97             public void run() {
 98                 synchronized (mProcessCpuTracker) {
 99                     mProcessCpuInitLatch.countDown();
100                     mProcessCpuTracker.init();
101                 }
102                 while (true) {
103                     try {
104                         try {
105                             synchronized(this) {
106                                 final long now = SystemClock.uptimeMillis();
107                                 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
108                                 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
109                                 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
110                                 //        + ", write delay=" + nextWriteDelay);
111                                 if (nextWriteDelay < nextCpuDelay) {
112                                     nextCpuDelay = nextWriteDelay;
113                                 }
114                                 if (nextCpuDelay > 0) {
115                                     mProcessCpuMutexFree.set(true);
116                                     this.wait(nextCpuDelay);
117                                 }
118                             }
119                         } catch (InterruptedException e) {
120                         }
121                         updateCpuStatsNow();
122                     } catch (Exception e) {
123                         Slog.e(TAG, "Unexpected exception collecting process stats", e);
124                     }
125                 }
126             }
127         };
128 
129         Watchdog.getInstance().addMonitor(this);
130         Watchdog.getInstance().addThread(mHandler);
131     }

主要内容包括:

  • 1>.主线程mHandlerThread创建并启动(Android UI线程)
  • 2>.创建了一个工作目录:/data/system (AMS的活动目录)
  • 3>.ActiveService,ActivityStackSupervisor的创建(专门用于管理Activity)
  • 4>.AMS的守护进程Watchdog(俗称 “看门狗”)

总结:

AMS的启动流程图:

  • AMS是在SystemServer进程中进行创建并启动的
  • 在AMS的服务启动过程中,通过构造函数进行了一些对象的创建和初始化工作(初Activity外其他3大组件的列表和调度对象的创建;内存、电池、权限、CPU等的监控等等相关对象的创建),并且通过start()方法启动服务(移除进程组、启动CPU线程、权限注册、电池服务等等)。
  • AMS创建并将对应服务启动之后,会通过setSystemProcess方法,将framework-res.apk的信息加入到SystemServer进程的LoadedApk中,并创建了SystemServer进程的ProcessRecord,加入到了mPidsSelfLocked,交给AMS来统一管理
  • AMS启动之后的后续工作,主要调用systemReady()和传入的goingCallBack来执行。主要是各种服务或者进程,等AMS启动完成后需要进一步完成的工作以及系统相关的初始化。
  • 桌面应用是在systemReady()方法中启动,systemUI是在goingCallback中完成。
  • 当桌面应用启动完成以后,发送开机广播ACTION_BOOT_COMPLETED。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈ChatGPT 和 对AI 的思考

新世纪以来&#xff0c;人工智能作为一个非常热门话题&#xff0c;一直收到大众的广泛的关注。从一开始的图像的分类&#xff0c;检测&#xff0c;到人脸的识别&#xff0c;到视频分析分类&#xff0c;到事件的监测&#xff0c;到基于图片的文本生成&#xff0c;到AI自动写小说…

机器学习-卷积神经网络CNN中的单通道和多通道图片差异

背景 最近在使用CNN的场景中&#xff0c;既有单通道的图片输入需求&#xff0c;也有多通道的图片输入需求&#xff0c;因此又整理回顾了一下单通道或者多通道卷积的差别&#xff0c;这里记录一下探索过程。 结论 直接给出结论&#xff0c;单通道图片和多通道图片在经历了第一…

QUIC 多流桥接、新增 DDS 协议转换代理

驽马十驾&#xff0c;功在不舍。新春之交&#xff0c;NanoMQ 继续保持稳步更新&#xff0c;最新的 0.16 版本将于三月初发布。NanoMQ 为用户提供了 2 个重要新功能&#xff1a;MQTT over QUIC 的多流桥接和 DDS 协议转换代理&#xff0c;拓宽了 NanoMQ 的弱网桥接传输性能和在边…

08 CSS05

目标&#xff1a; 1、定位 2、装饰 3、选择器拓展 一、定位 1、定位的基本介绍 2、定位的基本使用 3、静态定位 4、相对定位 5、绝对定位 6、子绝父相 7、固定定位 8、元素的层级关系1、定位的基本介绍 1.1 网页常见布局方式 &#xff08;1&#xff09;标准流 块级元素独…

CVTE前端面经(2023)

CVTE前端面经项目介绍&#xff08;重点&#xff09;在数据B中找到数组A对应的值&#xff0c;并把数组B对应的值放在数据最前面css1 定位2 外边距3 css高级应用3.1. 过渡3.2. 变形2. 浮动2.1 浮动元素特点2. 2 清除浮动3. html5语义标签4. 实现圣杯布局的两种方式4.1 定位浮动4.…

不会吧,难道真的有程序员不知道怎么接单赚钱吗?

随着大环境逐渐转好&#xff0c;跳槽、新工作、兼职等等机会都浮出水面。抛开跳槽、新工作不谈&#xff0c;今天就专门来说说程序员接单赚钱有哪些靠谱的平台。 首先分享一波关于接私活有哪些注意事项&#xff0c;给大家提个醒&#xff0c;避免盲目入坑。 一、程序员接单须知…

搬得进来,搬得出去!快来过一把数据迁移的“瘾”

欢迎访问OceanBase官网获取更多信息&#xff1a;https://www.oceanbase.com/ 经过前几次“剧透”&#xff0c;我们知道了 OceanBase 开发者大会有嘉宾、有演讲&#xff0c;有开源生态专场&#xff0c;也知道我们还会有 3 场 Hands-on Workshop 动手实验营&#xff0c;从部署到…

从LiveData迁移到Kotlin的 Flow,才发现是真的香!

LiveData 对于 Java 开发者、初学者或是一些简单场景而言仍是可行的解决方案。而对于一些其他的场景&#xff0c;更好的选择是使用 Kotlin 数据流 (Kotlin Flow)。虽说数据流 (相较 LiveData) 有更陡峭的学习曲线&#xff0c;但由于它是 JetBrains 力挺的 Kotlin 语言的一部分&…

一文搞定!postman接口自动化测试【附项目实战详解】

目录&#xff1a;导读 | 接口结果判断 功能区 脚本相关 代码模板 | 集合(批量)测试 变化的参数数据 定期任务 接口执行顺序 数据传递 | 解决依赖问题 假设场景 Postman 中的操作 运行 写在最后 附带项目实战教程地址&#xff1a;postman接口自动化测试使用教程项…

[计算机组成原理(唐朔飞 第2版)]第一章 计算机系统概论 第二章 计算机的发展及应用(学习复习笔记)

第1章 计算机系统概论 1.1 计算机系统简介 1.1.1 计算机的软硬件概念 计算机系统由“硬件”和“软件”两大部分组成。 硬件 是指计算机的实体部分&#xff0c;它由看得见摸得着的各种电子元器件&#xff0c;各类光、电、机设备的实物组成如主机、外部设备等 软件 软件看不见…

【protoc自定义插件】「go语言」实现rpc的服务映射成http的服务,protoc生成gin的插件,(详解实现原理及过程)

文章目录前言一、工程实践中如何更好的使用proto文件&#xff1f;二、protoc命令如何查询依赖的proto文件以及执行原理1. protoc命令如何查询依赖的proto文件2. protoc执行的插件加载原理是什么&#xff1f;3. proto文件中的package和go_package的作用三、protoc插件开发原理体…

春招冲刺(十): Vue2 技术复盘

vue2 技术复盘 Q1&#xff1a;MVVM框架的理解&#xff1f; MVVM模型&#xff1a; M&#xff1a;模型&#xff08;Model&#xff09;&#xff0c;data中的数据V&#xff1a;视图&#xff08;View&#xff09;&#xff0c;模板代码VM&#xff1a;视图模型&#xff08;ViewModel…

Me-and-My-Girlfriend-1靶场通关

Me-and-My-Girlfriend-1靶场通关 靶机ip:192.168.112.135 信息收集 端口&#xff1a;22、80 还是从80WEB服务器端口入手 对服务器目录进行扫描&#xff0c;扫出以下目录 访问80端口WEB服务&#xff0c;显示一段文字只允许本地用户访问。 一眼伪造ip&#xff0c;查看页面…

基于土壤数据与机器学习算法的农作物推荐算法代码实现

1.摘要 近年来&#xff0c;机器学习方法在农业领域的应用取得巨大成功&#xff0c;广泛应用于科 学施肥、产量预测和经济效益预估等领域。根据土壤信息进行数据挖掘&#xff0c;并在此基础上提出区域性作物的种植建议&#xff0c;不仅可以促进农作物生长从而带来经济效益&#…

为什么想到微前端,是巨石应用?

为什么想到微前端&#xff0c;是巨石应用&#xff1f; 现代的前端应用的发展趋势正在变得越来越富功能化&#xff0c;富交互化&#xff0c;也就是传说中的SPA(单页面应用)&#xff1b;这样越来越复杂的单体前端应用&#xff0c;背后的后端应用则是数量庞大的微服务集群。被一个…

STM32和emWin必须知道的那些事

emWin 是由德国 SEGGER 公司开发&#xff0c;可为图形 LCD 设计提供高级支持&#xff0c;极大简化了 LCD 设计。 为恩智浦ARM 微控制器用户免费提供的 emWin 图形库。在国内做嵌入式系统的大部分都使用 emwin&#xff0c; 其简单来说就是一套图形库。STemWin是SEGGER公司授权给…

HTML DOM 事件监听器

通过JavaScript&#xff0c;我们可以给页面的某些元素添加事件的监听器&#xff0c;当元素触发相应事件的时候监听器就会捕捉到这个事件并执行相应的代码。addEventListener() 方法实例当用户点击按钮时触发监听事件&#xff1a;document.getElementById("myBtn").ad…

Balsamiq Wireframes 安装配置

文章目录Balsamiq Wireframes 安装配置一、简介二、软件特色1、零学习曲线&#xff0c;随时随地提供强大功能2. 专为协作而设计3. 每个人的第一个 UX工具三、Balsamiq Wireframes功能介绍1、工具列2、快速添加工具3、UI库4、帆布5、导航器面板6、键盘快捷键&#xff1a;四、安装…

经纬恒润再传佳讯,斩获大奖

阳春二月&#xff0c;经纬恒润屡传佳讯&#xff0c;凭借产品、研发等多方面的出色表现&#xff0c;再次斩获东风柳汽“优秀供应商”和广汽传祺“科技创新奖”&#xff0c;以实力印证良好口碑&#xff0c;不忘初心&#xff0c;载誉而行&#xff01; 东风柳汽&#xff1a;优秀供…

【信号量机制及应用】

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 一、信号量机制 二、信号量的应用 >利用信号量实现进程互斥   >利用信号量实现前驱关系   >利用记录型信号量实现同步 三、例题 四、参考 一、信号量机制 信号量是操作系统提…