Android Service重启恢复(Service进程重启)原理解析(二)

简介: Android Service重启恢复(Service进程重启)原理解析(二)

APP被杀后Service如何重启


Binder有个讣告机制,Server死后,会向Client发送一份通知,在这里,其实就是APP死掉后,会像ActivityManagerService发送一份讣告通知,AMS后面负责清理APP的场景,并看是否需要回复Service,进一步处理后续流程,ActivityManagerService会调用handleAppDiedLocked处理死去的进程:

<!--函数1-->
private final void handleAppDiedLocked(ProcessRecord app,
        boolean restarting, boolean allowRestart) {
    int pid = app.pid;
    boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
    ..,
<!--函数2-->    
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
    boolean restarting, boolean allowRestart, int index) {
   ...
   mServices.killServicesLocked(app, allowRestart);

进一步调用ActiveServcies的killServicesLocked,killServicesLocked负责清理已死进程的Service,如果有必要,还需要根据之前启动时的设置重启Service:

final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
    <!--先清理bindService,如果仅仅是bind先清理掉-->
   for (int i = app.connections.size() - 1; i >= 0; i--) {
        ConnectionRecord r = app.connections.valueAt(i);
        removeConnectionLocked(r, app, null);
    }
      ...     
    ServiceMap smap = getServiceMap(app.userId);
    <!--处理未正常stop的Service-->
    for (int i=app.services.size()-1; i>=0; i--) {
        ServiceRecord sr = app.services.valueAt(i);
          ...
        <!--  超过两次的要避免再次重启Service,但是进程还是会被唤醒 如果是系统应用则无视,仍旧重启-->
        if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
                &ApplicationInfo.FLAG_PERSISTENT) == 0) {
            bringDownServiceLocked(sr);
        } else if (!allowRestart || !mAm.isUserRunningLocked(sr.userId, false)) {
           <!--不准重启的-->
            bringDownServiceLocked(sr);
        } else {
                <!--准备重启-->
            boolean canceled = scheduleServiceRestartLocked(sr, true);
            <!--看看是否终止一些极端的情况-->
            // Should the service remain running?  Note that in the
            // extreme case of so many attempts to deliver a command
            // that it failed we also will stop it here.
            <!-重启次数过多的话canceled=true(主要针对重发intent的)-->
            if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                if (sr.pendingStarts.size() == 0) {
                    sr.startRequested = false;...
                    if (!sr.hasAutoCreateConnections()) {
                        bringDownServiceLocked(sr);
             } }  }
        }
    }

这里有些限制,比如重启两次都失败,那就不再重启Service,但是系统APP不受限制,bindService的那种先不考虑,其他的为被正常stop的都会调用scheduleServiceRestartLocked进行重启登记,不过对于像START_NOT_STICKY这种,登记会再次被取消,sr.stopIfKilled就是在这里被用到。先看下    scheduleServiceRestartLocked,它的返回值也会影响是否需要重启:

private final boolean scheduleServiceRestartLocked(ServiceRecord r,
        boolean allowCancel) {
    boolean canceled = false;
    ServiceMap smap = getServiceMap(r.userId);
    if (smap.mServicesByName.get(r.name) != r) {
        ServiceRecord cur = smap.mServicesByName.get(r.name);
        Slog.wtf(TAG, "Attempting to schedule restart of " + r
                + " when found in map: " + cur);
        return false;
    }
    final long now = SystemClock.uptimeMillis();
    if ((r.serviceInfo.applicationInfo.flags
            &ApplicationInfo.FLAG_PERSISTENT) == 0) {
        long minDuration = SERVICE_RESTART_DURATION;
        long resetTime = SERVICE_RESET_RUN_DURATION;
        // Any delivered but not yet finished starts should be put back
        // on the pending list.
        // 在clean的时候会处理
        // 这里仅仅是要处理的需要deliveredStarts intent
        // remove task的被清理吗
        final int N = r.deliveredStarts.size();
        // deliveredStarts的耗时需要重新计算
        if (N > 0) {
            for (int i=N-1; i>=0; i--) {
                ServiceRecord.StartItem si = r.deliveredStarts.get(i);
                si.removeUriPermissionsLocked();
                if (si.intent == null) {
                    // We'll generate this again if needed.
                } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
                        && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
                    // 重启的时候
                    // 重启的时候,deliveredStarts被pendingStarts替换掉了
                    // 也就说,这个时候由死转到活
                    r.pendingStarts.add(0, si);
                    // 当前时间距离上次的deliveredTime,一般耗时比较长
                    long dur = SystemClock.uptimeMillis() - si.deliveredTime;
                    dur *= 2;
                    if (minDuration < dur) minDuration = dur;
                    if (resetTime < dur) resetTime = dur;
                } else {
                    canceled = true;
                }
            }
            r.deliveredStarts.clear();
        }
       r.totalRestartCount++;
        // r.restartDelay第一次重启
        if (r.restartDelay == 0) {
            r.restartCount++;
            r.restartDelay = minDuration;
        } else {
            // If it has been a "reasonably long time" since the service
            // was started, then reset our restart duration back to
            // the beginning, so we don't infinitely increase the duration
            // on a service that just occasionally gets killed (which is
            // a normal case, due to process being killed to reclaim memory).
            <!--如果被杀后,运行时间较短又被杀了,那么增加重启延时,否则重置为minDuration,(比如内存不足,经常重杀,那么不能无限重启,增大延时)-->
            if (now > (r.restartTime+resetTime)) {
                r.restartCount = 1;
                r.restartDelay = minDuration;
            } else {
                r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
                if (r.restartDelay < minDuration) {
                    r.restartDelay = minDuration;
                }
            }
        }
       <!--计算下次重启的时间-->
        r.nextRestartTime = now + r.restartDelay;
        <!--两个Service启动至少间隔10秒,这里的意义其实不是很大,主要是为了Service启动失败的情况,如果启动成功,其他要启动的Service会被一并直接重新唤起,-->
        boolean repeat;
        do {
            repeat = false;
            for (int i=mRestartingServices.size()-1; i>=0; i--) {
                ServiceRecord r2 = mRestartingServices.get(i);
                if (r2 != r && r.nextRestartTime
                        >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
                        && r.nextRestartTime
                        < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
                    r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
                    r.restartDelay = r.nextRestartTime - now;
                    repeat = true;
                    break;
                }
            }
        } while (repeat);
    } else {
    <!--系统服务,即可重启-->
        // Persistent processes are immediately restarted, so there is no
        // reason to hold of on restarting their services.
        r.totalRestartCount++;
        r.restartCount = 0;
        r.restartDelay = 0;
        r.nextRestartTime = now;
    }
     if (!mRestartingServices.contains(r)) {
        <!--添加一个Service-->
        mRestartingServices.add(r);
        ...
    }
    mAm.mHandler.removeCallbacks(r.restarter);
    // postAtTime
    mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
    <!--校准一下真实的nextRestartTime,dump时候可以看到-->
    r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
    ...
    return canceled;
}

scheduleServiceRestartLocked主要作用是计算重启延时,并发送重启的消息到Handler对应的MessageQueue,对于需要发送Intent的Service,他们之前的Intent被暂存在delivered, 在恢复阶段,原来的deliveredStarts会被清理,转换到pendingStart列表中,后面重新启动时候会根据pendingStart重发Intent给Service,调用其onStartCommand。不过对于这种Service,其启动恢复的时间跟其运行时间有关系,距离startService时间越长,其需要恢复的延时时间就越多,后面会单独解释。


image.png

另外,如果Service重启的时间间隔过短,则说明被杀的太迅速,很可能是系统资源不足,这个时候就逐步拉大重启时间。其次,什么时候Cancle重新启动呢?只有deliveredStarts非空(START_DELIVER_INTENT),并且回调onStartCommand失败的次数>=2,或者成功的次数>=6的时候,比如:对于START_DELIVER_INTENT,如果被杀超过6次,AMS会清理该Service,不会再重启了。另外如果重启的Service可有很多个,为了避免重启时间太接近,多个Service预置的重启间隔最少是10S,不过,并不是说Service真的需要间隔10s才能重启,而是说,如果前一个Service重启失败或者太慢,要至少10s后才重启下一个,如果第一个Service就重启成功,同时进程也启动成功,那么所有的Service都会被立刻唤起,而不需要等到真正的10秒延时间隔。


image.png

image.png

可以看到,虽然pendingStart中Service重启的间隔是至少相隔10秒,但是一个Service启动成功后,所有的Service都被唤起了,虽然还没有到之前预置的启动时机。这是为什么?因为,如果在进程未启动的时候启动Service,那么需要先启动进程,之后attach Application ,在attatch的时候,除了启动自己Service,还要将其余等待唤醒的Service一并唤起,源码如下:

boolean attachApplicationLocked(ProcessRecord proc, String processName)
        throws RemoteException {
    boolean didSomething = false;
    ...
    // 只要是一个起来了,就立刻重新启动所有Service,进程已经活了,就无须等待
    if (mRestartingServices.size() > 0) {
        ServiceRecord sr = null;
        for (int i=0; i<mRestartingServices.size(); i++) {
            sr = mRestartingServices.get(i);
            if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                    || !processName.equals(sr.processName))) {
                continue;
            }
            <!--清除旧的,-->
            mAm.mHandler.removeCallbacks(sr.restarter);
            <!--添加新的-->
            mAm.mHandler.post(sr.restarter);
        }
    }
    return didSomething;
}

可以看到,attachApplicationLocked的时候,会将之前旧的含有10秒延迟间隔的restarter清理掉,并重新添加无需延时的重启命令,这样那些需要重启的Service就不用等到之前设定的延时就可以重新启动了。还有什么情况,需要考虑呢,看下面的:


<!-重启次数过多的话canceled=true(主要针对重发intent的)-->
            if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                if (sr.pendingStarts.size() == 0) {
                    sr.startRequested = false;...
                    if (!sr.hasAutoCreateConnections()) {
                        bringDownServiceLocked(sr);
             } }  }
        }
  • 对于START_STICKY,scheduleServiceRestartLocked返回值一定是false,delay的时间是1S,并且由于其stopIfKilled是false,所以一定会被快速重启,不会走bringDownServiceLocked流程
  • 对于STAR_NO_STICKY,scheduleServiceRestartLocked返回值是flase,但是stopIfKilled是true,另外其pendingStarts列表为空,如果没有被其他存活的Activity绑定,那么需要走bringDownServiceLocked流程,也就是说,不会被重启。


处理完上述逻辑后,ServiceRestarter就会被插入到MessegeQueue等待执行,之后调用performServiceRestartLocked-> bringUpServiceLocked-> realStartServiceLocked进一步处理Service的重启。

private class ServiceRestarter implements Runnable {
    private ServiceRecord mService;
    void setService(ServiceRecord service) {
        mService = service;
    }
    public void run() {
        synchronized(mAm) {
            performServiceRestartLocked(mService);
        }
    }
}
final void performServiceRestartLocked(ServiceRecord r) {
// 如果被置空了,也是不用重启
if (!mRestartingServices.contains(r)) {
    return;
}
try {
    bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
} catch (TransactionTooLargeException e) {
    // Ignore, it's been logged and nothing upstack cares.
}

}

之前第一次启动的时候看过了,这里再来看复习一下,主要看不同的点,其实主要是针对START_STICKY的处理:


private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
       ...
    <!--恢复:这里应该主要是给start_sticky用的,恢复的时候触发调用onStartCommand-->
    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                null, null));
    }
    <!--处理onstartComand-->
    sendServiceArgsLocked(r, execInFg, true);
    ...

对于START_STICKY需要重启,之前说过了,但是怎么标记需要重新调用onStartCommand呢?上面的realStartServiceLocked会主动添加一个ServiceRecord.StartItem到pendingStarts,因为这个时候,对于START_STICKY满足如下条件。

r.startRequested && r.callStart && r.pendingStarts.size() == 0

不过,这个Item没有Intent,也就说,回调onStartCommand的时候,没有Intent传递给APP端,接下来的sendServiceArgsLocked跟之前的逻辑没太大区别,不再分析,下面再说下为什么START_REDELIVER_INTENT比较耗时。


被杀重启时候,为什么    START_REDELIVER_INTENT通常比START_STICK延时更多


之前说过,在onStartCommand返回值是START_REDELIVER_INTENT的时候,其重启恢复的延时时间跟Service的启动时间有关系。具体算法是:从start到now的时间*2,距离启动时间越长,restart的延时越多。

 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
            boolean allowCancel) {
        boolean canceled = false;
    ...
    final int N = r.deliveredStarts.size();
        // deliveredStarts的耗时需要重新计算
        if (N > 0) {
        ...
            if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
                                && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
                            r.pendingStarts.add(0, si);
                            // 当前时间距离上次的deliveredTime,一般耗时比较长
                            long dur = SystemClock.uptimeMillis() - si.deliveredTime;
                            dur *= 2;
                            if (minDuration < dur) minDuration = dur;
                            if (resetTime < dur) resetTime = dur;
                        }

如果设置了START_REDELIVER_INTENT,这里的deliveredStarts就一定非空,因为它持有startService的Intent列表,在这种情况下,重启延时是需要重新计算的,一般是是2*(距离上次sendServiceArgsLocked的时间(比如由startService触发))


long dur = SystemClock.uptimeMillis() - si.deliveredTime;

比如距离上次startService的是3分,那么它就在6分钟后重启,如果是半小时,那么它就在一小时后启动,


image.png而对于START_STICK,它的启动延时基本上是系统设置的Service最小重启延时单位,一般是一秒:

static final int SERVICE_RESTART_DURATION = 1*1000;


image.png

所以如果你需要快速重启Service,那么就使用START_STICK,不过START_STICK不会传递之前Intent信息,上面分析都是假设进程被意外杀死,那么用户主动从最近的任务列表删除的时候,也会重启,有什么不同吗?


从最近任务列表删除,如何处理Service的重启


左滑删除有时候会导致进程被杀死,这个时候,未被stop的Service也是可能需要重新启动的,这个时候跟之前的有什么不同吗?在这种情况下Service的onTaskRemoved会被回调。

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);
}

左滑删除TASK会调用AMS的cleanUpRemovedTaskLocked,这个函数会先处理Service的,并回调其onTaskRemoved,之后杀进程,杀进程之后的逻辑同样走binder讣告机制,跟之前的恢复没什么区别,这里主要看看onTaskRemoved,如果不需要重启,可以在这里做下处理:

private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {
    ...
    // Find any running services associated with this app and stop if needed.
    <!--先处理Service,如果有必要清理Service-->
    mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
    if (!killProcess) {
        return;
    }
    <!--找到跟改Task相关的进程,并决定是否需要kill-->
    ArrayList<ProcessRecord> procsToKill = new ArrayList<>();
    ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
    for (int i = 0; i < pmap.size(); i++) {
       SparseArray<ProcessRecord> uids = pmap.valueAt(i);
        for (int j = 0; j < uids.size(); j++) {
            ProcessRecord proc = uids.valueAt(j);
            ...<!--满足条件的等待被杀 (不是Home,)-->
            procsToKill.add(proc);
        }
    }
   // 如果可以即可杀,就立刻杀,否则等待下一次评估oomadj的时候杀,不过,总归是要杀的 
    for (int i = 0; i < procsToKill.size(); i++) {
        ProcessRecord pr = procsToKill.get(i);
        if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                && pr.curReceiver == null) {
            pr.kill("remove task", true);
        } else {
            pr.waitingToKill = "remove task";
        }
    }
}

ActiveServices的cleanUpRemovedTaskLocked

void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) {
    ArrayList<ServiceRecord> services = new ArrayList<>();
    ArrayMap<ComponentName, ServiceRecord> alls = getServices(tr.userId);
    for (int i = alls.size() - 1; i >= 0; i--) {
        ServiceRecord sr = alls.valueAt(i);
        if (sr.packageName.equals(component.getPackageName())) {
            services.add(sr);
        }
    }
    // Take care of any running services associated with the app.
    for (int i = services.size() - 1; i >= 0; i--) {
        ServiceRecord sr = services.get(i);
     // 如果是通过startRequested启动
        if (sr.startRequested) {
            if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
                stopServiceLocked(sr);
            } else {
            <!--作为remove的一部分,这里pendingStarts的add主要是为了回到onStartCommand,而且这个时候,进程还没死呢,否则通知个屁啊-->
                sr.pendingStarts.add(new ServiceRecord.StartItem(sr,  taskremover =true,
                        sr.makeNextStartId(), baseIntent, null));
                if (sr.app != null && sr.app.thread != null) {
                    try {
                        sendServiceArgsLocked(sr, true, false);
                    } ...
                }

其实从最近任务列表删除最近任务的时候,处理很简单,如果Service设置了ServiceInfo.FLAG_STOP_WITH_TASK,那么左滑删除后,Service不用重启,也不会处理 onTaskRemoved,直接干掉,否则,是需要往pendingStarts填充ServiceRecord.StartItem,这样在sendServiceArgsLocked才能发送onTaskRemoved请求,为了跟启动onStartCommand分开,ServiceRecord.StartItem的taskremover被设置成true,这样在回调ActiviyThread的handleServiceArgs就会走onTaskRemoved分支如下:

private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            if (data.args != null) {
                data.args.setExtrasClassLoader(s.getClassLoader());
                data.args.prepareToEnterProcess();
            }
            int res;
            // 如果没有 taskRemoved,如果taskRemoved 则回调onTaskRemoved
            if (!data.taskRemoved) {
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }
            ....

因此,从最近任务列表删除,可以看做是仅仅多了个一个onTaskRemoved在这个会调中,用户可以自己处理一些事情,比如中断一些Service处理的事情,保存现场等。


Android O 之后的变更


似乎Android O之后START_STICK的Service会重新唤起进程,但是onStartCommand不会被调用,这样似乎更合情理,不是startService启动的Service不会调用onStartCommand。


总结


  • 通过startService启动,但是却没有通过stopService结束的Service并不一定触发重新启动,需要设置相应的onStartCommand返回值,比如START_REDELIVER_INTENT、比START_STICK
  • START_REDELIVER_INTENT并不是重发最后一个Intent,看源码是所有Intent
  • START_REDELIVER_INTENT同START_STICK重启的延时不一样,START_STICK一般固定1s,而START_REDELIVER_INTENT较长,基本是距离startService的2倍。
  • 可以用来做保活,但是不推荐,而且国内也不怎么好用(MIUI、华为等都对AMS做了定制,限制较多)


目录
相关文章
|
Java 开发工具 Android开发
Android与iOS开发环境搭建全解析####
本文深入探讨了Android与iOS两大移动操作系统的开发环境搭建流程,旨在为初学者及有一定基础的开发者提供详尽指南。我们将从开发工具的选择、环境配置到第一个简单应用的创建,一步步引导读者步入移动应用开发的殿堂。无论你是Android Studio的新手还是Xcode的探索者,本文都将为你扫清开发道路上的障碍,助你快速上手并享受跨平台移动开发的乐趣。 ####
|
IDE Android开发 iOS开发
深入解析Android与iOS的系统架构及开发环境差异
本文旨在探讨Android和iOS两大主流移动操作系统在系统架构、开发环境和用户体验方面的显著差异。通过对比分析,我们将揭示这两种系统在设计理念、技术实现以及市场策略上的不同路径,帮助开发者更好地理解其特点,从而做出更合适的开发决策。
2138 2
|
11月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
213 20
|
XML JavaScript Android开发
【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式
本文总结了Android中几种常用的网络技术,包括WebView、HttpURLConnection、OKHttp和XML的Pull解析方式。每种技术都有其独特的特点和适用场景。理解并熟练运用这些技术,可以帮助开发者构建高效、可靠的网络应用程序。通过示例代码和详细解释,本文为开发者提供了实用的参考和指导。
493 15
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
427 6
|
存储 Linux API
深入探索Android系统架构:从内核到应用层的全面解析
本文旨在为读者提供一份详尽的Android系统架构分析,从底层的Linux内核到顶层的应用程序框架。我们将探讨Android系统的模块化设计、各层之间的交互机制以及它们如何共同协作以支持丰富多样的应用生态。通过本篇文章,开发者和爱好者可以更深入理解Android平台的工作原理,从而优化开发流程和提升应用性能。
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
561 4
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
288 4
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####

推荐镜像

更多