安卓9.0trim相关源码分析

1、trim是什么? 
        一条ATA指令,由操作系统发送给SSD主控制器,告诉它哪些数据占有的地址是“无效的”。 其实就是操作系统将一部分的控制权交给了SSD主控制器,让操作系统与SSD主控制器有一个互动。因为闪存需要先擦除才能再次写入数据,要得到空闲的闪存空间,SSD必须复制所有“有效”页到新的“空白页”里,并且擦除旧块,即垃圾回收;避免了在操作系统要重新写入数据时, SSD才会知道哪些地址是无效的情况。这样就可以在适当的时机做最好的优化。 简而言之,这是一种能够让闪存长期工作后,也能维持高速度的技术。不少人长期使用安卓机后表示,安卓怎么就越用越卡,无论怎么刷系统清数据也没法回到刚买时的流畅度。这往往是由于长期使用后,闪存的垃圾回收效率大大降低,使得安卓机的I/O性能大跌造成的。安卓4.3支持Trim技术,能够大幅提升闪存垃圾回收效率,让闪存始终保持接近原始状态的高速度。  这样做既提高了“硬盘速度”, 同时也延长了SSD的使用寿命,垃圾回收!!!

2.trim触发条件?
1.开机触发一次
2.每日凌晨3点触发trim,不过这个要在充电状态,或者电量不低于80%条件下.

1.凌晨3点触发trim

xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
//系统准备好就会创建fstrim计划.
735    private void handleSystemReady() {
736        initIfReadyAndConnected();
737        resetIfReadyAndConnected();
738
739        // 开始计划日常fstrim操作
740        MountServiceIdler.scheduleIdlePass(mContext);
741
742        ......
753    }

JobScheduler是Android L(API21)新增的特性,该框架将在执行作业(也就是JobInfo)时智能化,并尽可能地批量并推迟JobInfo,从而节省电量。Android8.0及以上建议使用JobScheduler来启动服务。
JobScheduler是作业发布器,它的任务是分发设置作业JobInfo。JobInfo是作业包装体,它包含了任务执行的条件、开始时间、截止时间、具体任务、需要传递的参数等信息。JobService是JobInfo中的参数,它们是条件到了真正执行具体任务。
JobInfo通过Builder模式JobInfo.Builder创建实例,JobInfo.Builder可以设置多个参数,其中作业启动条件必须限制一个。

      /**
96     * Schedule the idle job that will ping the mount service
97     */
98    public static void scheduleIdlePass(Context context) {
99        JobScheduler tm = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
100        //获取凌晨3点的时间
101        Calendar calendar = tomorrowMidnight();
           //获取到凌晨3点还差的秒数.
102        final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis();
103
104        JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService);
105        builder.setRequiresDeviceIdle(true); //如果设置为true,请确保在设备处于活动使用状态时不会运行此作业。
106        builder.setRequiresCharging(true); //指定要运行此作业,设备必须正在充电
107        builder.setMinimumLatency(timeToMidnight);//延迟到指定作业时间。
108        tm.schedule(builder.build()); //发布作业.
109    }

//满足触发时间会在MountServiceIdler里执行onStartJob.

xref: /frameworks/base/services/core/java/com/android/server/MountServiceIdler.java

56    @Override
57    public boolean onStartJob(JobParameters params) {
58        // First have the activity manager do its idle maintenance.  (Yes this job
59        // is really more than just mount, some day it should be renamed to be system
60        // idleer).
61        try {
              //执行空闲维护,主要发送开始维护广播?
62            ActivityManager.getService().performIdleMaintenance();
63        } catch (RemoteException e) {
64        }
65        // The mount service will run an fstrim operation asynchronously
66        // on a designated separate thread, so we provide it with a callback
67        // that lets us cleanly end our idle timeslice.  It's safe to call
68        // finishIdle() from any thread.
          //获取StorageManagerService的静态实例
70        StorageManagerService ms = StorageManagerService.sSelf;
71        if (ms != null) {
72            synchronized (mFinishCallback) {
73                mStarted = true;
74            }
              //调用StorageManagerService里方法,并传入回调函数mFinishCallback.
75            ms.runIdleMaint(mFinishCallback);
76        }
77        return ms != null;
78    }

xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
1890    void runIdleMaint(Runnable callback) {
1891        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1892
1893        try {
                //通过binder机制调用vold服务里面的runIdleMaint.
1894            mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1895                @Override
1896                public void onStatus(int status, PersistableBundle extras) {
1897                    // Not currently used
1898                }
1899                @Override
1900                public void onFinished(int status, PersistableBundle extras) {
1901                    if (callback != null) {
                            //当清理结束,获取一个handler,并发送下一个执行任务.会回调到MountServiceIdler里mFinishCallback
1902                        BackgroundThread.getHandler().post(callback);
1903                    }
1904                }
1905            });
1906        } catch (Exception e) {
1907            Slog.wtf(TAG, e);
1908        }
1909    }

//组织下一次作业清理任务.
private Runnable mFinishCallback = new Runnable() {
42        @Override
43        public void run() {
44            Slog.i(TAG, "Got mount service completion callback");
45            synchronized (mFinishCallback) {
46                if (mStarted) {
47                    jobFinished(mJobParams, false);
48                    mStarted = false;
49                }
50            }
51            // ... and try again tomorrow
52            scheduleIdlePass(MountServiceIdler.this);
53        }
54    };

xref: /system/vold/VoldNativeService.cpp

481binder::Status VoldNativeService::runIdleMaint(
482        const android::sp<android::os::IVoldTaskListener>& listener) {
483    ENFORCE_UID(AID_SYSTEM);
484    ACQUIRE_LOCK;
485    //运行空闲维护
486    std::thread([=]() {
487        android::vold::RunIdleMaint(listener);
488    }).detach();
489    return ok();
490}
//调用vold里面的IdleMaint进行磁盘整理.这里面涉及很底层的东西还是比较难理解的,但是从命名来看,还是能够看的出大概处理流程的.
xref: /system/vold/IdleMaint.cpp

310int RunIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
311    std::unique_lock<std::mutex> lk(cv_m);
312    if (idle_maint_stat != IdleMaintStats::kStopped) {
313        LOG(DEBUG) << "idle maintenance is already running";
314        if (listener) {
315            android::os::PersistableBundle extras;
316            listener->onFinished(0, extras);
317        }
318        return android::OK;
319    }
320    idle_maint_stat = IdleMaintStats::kRunning;
321    lk.unlock();
322
323    LOG(DEBUG) << "idle maintenance started";
324
325    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
326
327    std::list<std::string> paths;
328    addFromFstab(&paths, PathTypes::kBlkDevice);
329    addFromVolumeManager(&paths, PathTypes::kBlkDevice);
330
331    startGc(paths);
332
333    bool gc_aborted = waitForGc(paths);
334
335    stopGc(paths);
336
337    lk.lock();
338    idle_maint_stat = IdleMaintStats::kStopped;
339    lk.unlock();
340
341    cv_stop.notify_one();
342
343    if (!gc_aborted) {
344        Trim(nullptr);
345        runDevGc();
346    }
347
348    if (listener) {
349        android::os::PersistableBundle extras;
           //调用回调通知清理结束
350        listener->onFinished(0, extras);
351    }
352
353    LOG(DEBUG) << "idle maintenance completed";
354
355    release_wake_lock(kWakeLock);
356
357    return android::OK;
358}

2.开机fstrim

xref: /frameworks/base/services/java/com/android/server/SystemServer.java
//开机的时候在SystemServer启动服务调用PackageManagerService的performFstrimIfNeeded进行磁盘整理.
private void startOtherServices() {
1010        traceBeginAndSlog("PerformFstrimIfNeeded");
1011        try {
1012            mPackageManagerService.performFstrimIfNeeded();
1013        } catch (Throwable e) {
1014            reportWtf("performing fstrim", e);
1015        }
1016        traceEnd();
}
xref: /frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
8928    @Override
8929    public void performFstrimIfNeeded() {
8930        enforceSystemOrRoot("Only the system can request fstrim");
8931
8932        // Before everything else, see whether we need to fstrim.
8933        try {
8934            IStorageManager sm = PackageHelper.getStorageManager();
8935            if (sm != null) {
8936                boolean doTrim = false;
8937                final long interval = android.provider.Settings.Global.getLong(
8938                        mContext.getContentResolver(),
8939                        android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
8940                        DEFAULT_MANDATORY_FSTRIM_INTERVAL);
8941                if (interval > 0) {
8942                    final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
8943                    if (timeSinceLast > interval) {
8944                        doTrim = true;
8945                        Slog.w(TAG, "No disk maintenance in " + timeSinceLast
8946                                + "; running immediately");
8947                    }
8948                }
8949                if (doTrim) {
8950                    final boolean dexOptDialogShown;
8951                    synchronized (mPackages) {
8952                        dexOptDialogShown = mDexOptDialogShown;
8953                    }
8954                    if (!isFirstBoot() && dexOptDialogShown) {
8955                        try {
8956                            ActivityManager.getService().showBootMessage(
8957                                    mContext.getResources().getString(
8958                                            R.string.android_upgrading_fstrim), true);
8959                        } catch (RemoteException e) {
8960                        }
8961                    }
                        //调用StorageManagerService的runMaintenance进行磁盘整理.
8962                    sm.runMaintenance();
8963                }
8964            } else {
8965                Slog.e(TAG, "storageManager service unavailable!");
8966            }
8967        } catch (RemoteException e) {
8968            // Can't happen; StorageManagerService is local
8969        }
8970    }

//StorageManagerService中发送磁盘整理的消息
xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
947    void runIdleMaintenance(Runnable callback) {
948        mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
949    }
950
951    // Binder entry point for kicking off an immediate fstrim
952    @Override
953    public void runMaintenance() {
954        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
955        runIdleMaintenance(null);
956    }
              //在handler中调用fstrim
              case H_FSTRIM: {
576                    Slog.i(TAG, "Running fstrim idle maintenance");
577
578                    // Remember when we kicked it off
579                    try {
580                        mLastMaintenance = System.currentTimeMillis();
581                        mLastMaintenanceFile.setLastModified(mLastMaintenance);
582                    } catch (Exception e) {
583                        Slog.e(TAG, "Unable to record last fstrim!");
584                    }
585
586                    // TODO: Reintroduce shouldBenchmark() test
587                    fstrim(0, null);
588
589                    // invoke the completion callback, if any
590                    // TODO: fstrim is non-blocking, so remove this useless callback
591                    Runnable callback = (Runnable) msg.obj;
592                    if (callback != null) {
593                        callback.run();
594                    }
595                    break;
596                }
        //通过binder机制调用vold中的fstrim,同时实现VoldTaskListener,当vold处理完会通知到这里.
1849    @Override
1850    public void fstrim(int flags, IVoldTaskListener listener) {
1851        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1852
1853        try {
1854            mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1855                @Override
1856                public void onStatus(int status, PersistableBundle extras) {
1857                    dispatchOnStatus(listener, status, extras);
1858
1859                    // Ignore trim failures
1860                    if (status != 0) return;
1861
1862                    final String path = extras.getString("path");
1863                    final long bytes = extras.getLong("bytes");
1864                    final long time = extras.getLong("time");
1865
1866                    final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1867                    dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1868
1869                    synchronized (mLock) {
1870                        final VolumeRecord rec = findRecordForPath(path);
1871                        if (rec != null) {
1872                            rec.lastTrimMillis = System.currentTimeMillis();
1873                            writeSettingsLocked();
1874                        }
1875                    }
1876                }
1877
1878                @Override
1879                public void onFinished(int status, PersistableBundle extras) {
1880                    dispatchOnFinished(listener, status, extras);
1881
1882                    // TODO: benchmark when desired
1883                }
1884            });
1885        } catch (RemoteException e) {
1886            throw e.rethrowAsRuntimeException();
1887        }
1888    }

xref: /system/vold/VoldNativeService.cpp
470binder::Status VoldNativeService::fstrim(int32_t fstrimFlags,
471        const android::sp<android::os::IVoldTaskListener>& listener) {
472    ENFORCE_UID(AID_SYSTEM);
473    ACQUIRE_LOCK;
474
475    std::thread([=]() {
476        android::vold::Trim(listener);
477    }).detach();
478    return ok();
479}
//vold中主要做trim的函数,涉及也是比较底层,比较难理解,大家自己看代码琢磨吧.
xref: /system/vold/IdleMaint.cpp
143void Trim(const android::sp<android::os::IVoldTaskListener>& listener) {
144    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
145
146    // Collect both fstab and vold volumes
147    std::list<std::string> paths;
148    addFromFstab(&paths, PathTypes::kMountPoint);
149    addFromVolumeManager(&paths, PathTypes::kMountPoint);
150
151    for (const auto& path : paths) {
152        LOG(DEBUG) << "Starting trim of " << path;
153
154        android::os::PersistableBundle extras;
155        extras.putString(String16("path"), String16(path.c_str()));
156
157        int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
158        if (fd < 0) {
159            PLOG(WARNING) << "Failed to open " << path;
160            if (listener) {
161                listener->onStatus(-1, extras);
162            }
163            continue;
164        }
165
166        struct fstrim_range range;
167        memset(&range, 0, sizeof(range));
168        range.len = ULLONG_MAX;
169
170        nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
171        if (ioctl(fd, FITRIM, &range)) {
172            PLOG(WARNING) << "Trim failed on " << path;
173            if (listener) {
174                listener->onStatus(-1, extras);
175            }
176        } else {
177            nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
178            LOG(INFO) << "Trimmed " << range.len << " bytes on " << path
179                    << " in " << nanoseconds_to_milliseconds(time) << "ms";
180            extras.putLong(String16("bytes"), range.len);
181            extras.putLong(String16("time"), time);
182            if (listener) {
183                listener->onStatus(0, extras);
184            }
185        }
186        close(fd);
187    }
188    //trim结束通知回调finish.
189    if (listener) {
190        android::os::PersistableBundle extras;
191        listener->onFinished(0, extras);
192    }
193
194    release_wake_lock(kWakeLock);
195}

以上就是安卓磁盘整理相关代码,希望对大家有点帮忙吧,继续学习..

参考:
https://blog.csdn.net/su1987582/article/details/48729401
https://blog.csdn.net/u013795543/article/details/80861953

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值