android存储2--初始化.存储service的启动

android版本:android-11.0.0_r21
http://aospxref.com/android-11.0.0_r21/

android存储初始化分3个阶段:
1)清理环境。因android支持多用户,解锁后登录的可能是另一个用户,需把之前用户执行的一些信息清理干净。《android存储1--初始化.清理环境》已做分析,总结如下:

  • start primary user
    发送START消息、H_BOOT_COMPLETED消息给其他service处理。
  • init用户目录的加密状态
    初始化软件加解密的device的用户目录加密状态;对于硬件加密的device,什么事也不做。
  • reset external storage service
    umount外部存储、关闭mount service的所有connection。按电源键开机,外部存储还没有挂载,所以不需要卸载任何存储设备,也不需要关闭任何connection。
  • reset vold service
    销毁volume、重置disk对象、清空用户、添加用户。开机场景不需要销毁volume、重置disk对象、清空用户。
  • 添加用户
    在mAddedUsers中记录主用户。

2)启动存储服务(mount、vold、storaged这些service)。
3)挂载emulated存储(这系列文章只分析emulated存储)。

   本文分析“启动存储服务”,涉及mount、vold、storaged service的启动流程。

一、存储相关的service

1,service介绍

存储有3个关键service:mount、vold、storaged,通过adb shell "service list"可以看到。

service代码:

service 代码路径
mount service frameworks/base/services/core/java/com/android/server/StorageManagerService.java
vold service system/vold 目录
(注意,虽然vold是一个用户态程序,但它的log默认在内核里,需通过dmesg查看)
storaged service system/core/storaged 目录

mount service负责mount和umount存储设备或存储卷,提供文件系统的访问接口。它的mount、umount请求下发给native层的vold处理。

vold (Volume Daemon)位于framework和kernel之间,管理存储卷的生命周期、处理mount service的mount和umount请求,以及提供存储卷的管理接口。
vold主要功能:
1)监听内核的存储设备uevent事件,并上报给mount service。
2)处理mount service下发的mount、umount请求。

storaged是一个deamon进程提供存储相关的统计数据(磁盘使用信息、应用io信息、存储寿命信息等),并通过向应用程序和系统组件提供 API 接口,使它们能够监控和管理存储资源的使用情况。提供的命令如下:

命令 输出说明
storaged或storaged -s

注册storaged service和storaged_pri service。
系统启动时int进程解析/system/etc/init/storaged.rc,执行storaged命令。

我们在调试的过程中,不需要再执行storaged命令了。

storaged -u
storaged -t
调试时,该命令用的比较多

/       

storaged的help信息:
-u Dump uid I/O usage to stdout
-t Dump task I/O usage to stdout

但是,system/core/storaged/main.cpp的main函数中,-u,-t调用的都是storaged_service->dumpUids(&uid_io),所以功能是一样的。
storaged -p Dump I/O perf history to stdout

2,service之间的关系

mount、vold、storaged之间的层次关系如下:

android存储2--初始化.存储service的启动_第1张图片

 图中标号说明:

①:looper线程监听ACTION_USER_ADDED和ACTION_USER_REMOVED消息。

StorageManagerService::StorageManagerService --> mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler)注册了BroadcastReceiver ,接收ACTION_USER_ADDED和ACTION_USER_REMOVED类型的 IntentFilter 广播消息, 参数mHandle所代表的线程上执行 BroadcastReceiver。

在StorageManagerService方法中,mHandler = new StorageManagerServiceHandler(hthread.getLooper()),所以Handler 代表的线程是looper线程。

mount service收到ACTION_USER_ADDED和ACTION_USER_REMOVED后,会做mount或者unmount操作。

②:mount service设置一个监听器,监听vold状态。

StorageManagerService::connectVold --> mVold = IVold.Stub.asInterface(binder)获取vold service的Binder对象,接着mount service通过mVold.setListener(mListener)设置监听器监听vold状态变化,监听器回调方法在StorageManagerService的匿名内部类中(见private final IVoldListener mListener = new IVoldListener.Stub()处的匿名类)。一旦vold状态变化,就会执行监听器回调方法,见⑤。

③:mount service获取storaged的binder对象,需要的时候执行storaged中的方法。

StorageManagerService::connectStoraged --> mStoraged = IStoraged.Stub.asInterface(binder)获取storaged service的Binder对象。mount service接收到相关事件后,比如unlock user,remove user等,执行storaged中的函数mStoraged.onUserStarted(userId),mStoraged.onUserStopped(userId)等。

④:VoldNativeService执行VolumeManager中的方法。

VoldNativeService通过类似于translate(VolumeManager::Instance()->XXX执行VolumeManager中的方法。比如VoldNativeService::onUserAdded --> translate(VolumeManager::Instance()->onUserAdded(userId, userSerial)),执行的是VolumeManager::onUserAdded。

⑤:VolumeManager上报存储设备事件给mount service。

用户add或删除,需要mount或者umount掉emulated storage;热插拔存储设备,kernel会上报uevent事件,这些都会引起vold状态变化,此时mount service在②中设置的监听器就监听到这些事件,执行对应的监听器回调方法。

⑥:NetlinkManager初始化socket,用于接收kernel的uevent事件。

system/vold/main.cpp中通过nm = NetlinkManager::Instance()实例化了一个NetlinkManager,用于接收kernel的uevent事件。

⑦:VolumeManager执行系统调用,执行mount等操作。

VolumeManager通过VolumeManager类执行kernel的系统调用,比如VolumeManager::mountAppFuse --> android::vold::MountAppFuse --> RunCommand --> mount等。

二、mount service的启动

SystemServer类定义了STORAGE_MANAGER_SERVICE_CLASS常量:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/java/com/android/server/SystemServer.java#SystemServer


private static final String JOB_SCHEDULER_SERVICE_CLASS =
              "com.android.server.job.JobSchedulerService";
private static final String LOCK_SETTINGS_SERVICE_CLASS =
              "com.android.server.locksettings.LockSettingsService$Lifecycle";
private static final String STORAGE_MANAGER_SERVICE_CLASS =

http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/java/com/android/server/SystemServer.java#SystemServer

Android启动时,SystemServer 进程启动其他系统服务(startOtherServices)。在这个过程中,SystemServer类定义的常量被用于加载各个服务。
以com.android.server.StorageManagerService$Lifecycle为例,看一下service的注册过程。

SystemServer::run
  --> startOtherServices(t)
        --> mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS)
              --> SystemService startService(String className)
                    -->  T startService(Class serviceClass)
                          --> startService(@NonNull final SystemService service)
                                --> service.onStart();以存储为例,即StorageManagerService$Lifecycle::onStart
                                      --> publishBinderService("mount", mStorageManagerService) //注册到SystemServiceManager中                                 

service.onStart对应的StorageManagerService$Lifecycle::onStart函数:

http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#255

210  class StorageManagerService extends IStorageManager.Stub
211          implements Watchdog.Monitor, ScreenObserver {
          ……
246      public static class Lifecycle extends SystemService {
247          private StorageManagerService mStorageManagerService;
248  
249          public Lifecycle(Context context) {
250              super(context);
251          }
252  
253          @Override
254          public void onStart() {
255              mStorageManagerService = new StorageManagerService(getContext());
256              publishBinderService("mount", mStorageManagerService);
257              mStorageManagerService.start();
258          }

255行,实例化一个StorageManagerService对象,在其构造函数:

1)通过HandlerThread hthread = new HandlerThread(TAG)创建一个消息处理线程,线程名为“StorageManagerService”(注意,内核记录的线程名最多16个字符,所以ps -AT看到的线程名是不完整的),处理ACTION_USER_ADDED和ACTION_USER_REMOVED事件。

2)通过mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled)创建一个StorageSessionController,用来控制访问外部存储。

256行,publishBinderService将255行新创建的StorageManagerService以“mount”名字注册到serviceManager中(可通过adb shell "service list"命令查看service)

257行, mStorageManagerService.start()启动service,代码如下:

1891      private void start() {
1892          connectStoraged();
1893          connectVold();
1894      }

 connectStoraged()和connectVold()都是在StorageManagerService类中定义的,简化后的代码:

private void connectStoraged() {
1897          IBinder binder = ServiceManager.getService("storaged");
			  ……
1914          mStoraged = IStoraged.Stub.asInterface(binder);
1926      }
1927  
1928      private void connectVold() {
1929          IBinder binder = ServiceManager.getService("vold"); // ⑧
			  ……
1946          mVold = IVold.Stub.asInterface(binder); // ⑨
1948          mVold.setListener(mListener); // ⑩
1964      }

connectStoraged() 设置 IStoraged  mStoraged变量,connectVold() 设置 IVold  mVold变量。以connectVold()为例说明代码:

⑧:获取名为 "vold" 的服务的 Binder 对象。

⑨:将获取到的 Binder 对象转换为 IVold 接口的实例,并将其赋值给变量mVold。

⑩:设置监听器,监听到mVold状态变化时,执行mListener的回调函数,比如onDiskCreated,onVolumeCreated等。

三、vold service的启动

init.rc脚本中定义了start vold语句,inti进程启动vold服务*(这里说的服务是linux中的service,不是android中的service)。
http://aospxref.com/android-11.0.0_r21/xref/system/core/rootdir/init.rc#453
 

451 on early-fs
452     # Once metadata has been mounted, we'll need vold to deal with userdata checkpointing
453     start vold

vold服务*(linux中的service)的描述:
vold.rc - OpenGrok cross reference for /system/vold/vold.rc

1 service vold /system/bin/vold \
2         --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
3         --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
4     class core
5     ioprio be 2
6     writepid /dev/cpuset/foreground/tasks
7     shutdown critical
8     group root reserved_disk

nti进程加载/system/bin/vold二进制文件,启动vold进程。system/vold/main.cpp文件中main函数简化如下:

int main(int argc, char** argv) {

    VolumeManager* vm;
    NetlinkManager* nm;

    //实例化一个VolumeManager,用于管理所有的volume,VolumeManager成员mDisks记录系统中所有的disk,Disk类描述disk,Disk成员mVolumes记录了本disk所有的分区。
    if (!(vm = VolumeManager::Instance())) {
        LOG(ERROR) << "Unable to create VolumeManager";
        exit(1);
    }

    //实例化一个NetlinkManager,用于接收kernel的uevent事件
    if (!(nm = NetlinkManager::Instance())) {
        LOG(ERROR) << "Unable to create NetlinkManager";
        exit(1);
    }

    //实例化一个VolumeBase,用来描述"/data/media"路径的emulated volume,并将该volume加入到mInternalEmulatedVolumes链表。注意,这个时候只是初始化了vloume(VolumeBase类型)的部分成员,并没有创建emulated volume,也即没有执行mount外部存储等一些列操作。
    if (vm->start()) {
        PLOG(ERROR) << "Unable to start VolumeManager";
        exit(1);
    }

    //通过BinderService::publish()发布"vold"服务。VoldNativeService::getServiceName返回的是"vold"字符串。
    if (android::vold::VoldNativeService::start() != android::OK) {
        LOG(ERROR) << "Unable to start VoldNativeService";
        exit(1);
    }

    //nm->start初始化了socket,启动NetlinkManager监听kernel的uevent事件。
    if (nm->start()) {
        PLOG(ERROR) << "Unable to start NetlinkManager";
        exit(1);
    }

    //当前线程加入到Binder线程池,一旦线程加入到Binder线程池中,它将持续监听并处理来自客户端的Binder调用请求。当有请求到达时,线程将调用相应的服务方法来处理请求,并将结果返回给客户端。
    android::IPCThreadState::self()->joinThreadPool();
}

main函数中的android::vold::VoldNativeService::start()发布vold service(android中的service概念,通过service list命令查看)。

四、storaged service的启动

storaged服务定义在system/core/storaged/storaged.rc中,编译刷机运行,脚本在/system/etc/init/storaged.rc。

system/core/init/main.cpp中main --> SecondStageMain --> LoadBootScripts --> parser.ParseConfig("/system/etc/init")代码如下:
http://aospxref.com/android-11.0.0_r21/xref/system/core/init/parser.cpp#184

184  bool Parser::ParseConfig(const std::string& path) {
185      if (is_dir(path.c_str())) {
186          return ParseConfigDir(path);
187      }
188      return ParseConfigFile(path);
189  }

/system/etc/init是一个目录,所以执行ParseConfigDir函数。

http://aospxref.com/android-11.0.0_r21/xref/system/core/init/parser.cpp#ParseConfigDir

157  bool Parser::ParseConfigDir(const std::string& path) {
158      LOG(INFO) << "Parsing directory " << path << "...";
159      std::unique_ptr config_dir(opendir(path.c_str()), closedir);
160      if (!config_dir) {
161          PLOG(INFO) << "Could not import directory '" << path << "'";
162          return false;
163      }
164      dirent* current_file;
165      std::vector files;
166      while ((current_file = readdir(config_dir.get()))) {
167          // Ignore directories and only process regular files.
168          if (current_file->d_type == DT_REG) {
169              std::string current_path =
170                  android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
171              files.emplace_back(current_path);
172          }
173      }
174      // Sort first so we load files in a consistent order (bug 31996208)
175      std::sort(files.begin(), files.end());
176      for (const auto& file : files) {
177          if (!ParseConfigFile(file)) {
178              LOG(ERROR) << "could not import file '" << file << "'";
179          }
180      }
181      return true;
182  }

ParseConfigDir遍历目录下的文件,然后调用ParseConfigFile启动/system/etc/init/storaged.rc定的storaged服务*(这里说的服务是linux中的service,不是android中的service)。

storaged服务描述:
http://aospxref.com/android-11.0.0_r21/xref/system/core/storaged/storaged.rc

1 service storaged /system/bin/storaged
2     class main
3     capabilities DAC_READ_SEARCH
4     priority 10
5     file /d/mmc0/mmc0:0001/ext_csd r
6     writepid /dev/cpuset/system-background/tasks
7     user root
8     group package_info

inti进程加载/system/bin/storaged二进制文件,启动storaged进程。system/core/storaged/main.cpp中main函数简化如下:

int main(int argc, char** argv) {

    // storaged或者storaged -s命令,周期性统计
    if (flag_main_service) { // start main thread
        // Start the main thread of storaged
        storaged_sp = new storaged_t();
        storaged_sp->init();
        storaged_sp->report_storage_info();
        pthread_t storaged_main_thread;
        errno = pthread_create(&storaged_main_thread, NULL, storaged_main, NULL);
        if (errno != 0) {
            PLOG(ERROR) << "Failed to create main thread";
            return -1;
        }

        if (StoragedService::start() != android::OK ||
            StoragedPrivateService::start() != android::OK) {
            PLOG(ERROR) << "Failed to start storaged service";
            return -1;
        }

        android::ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
        pthread_join(storaged_main_thread, NULL);

        return 0;
    }

    sp storaged_service = get_storaged_pri_service();
    if (storaged_service == NULL) {
        fprintf(stderr, "Cannot find storaged service.\nMaybe run storaged --start first?\n");
        return -1;
    }

    // 根据help信息:
    // storaged -u按uid统计io使用信息,storaged -t按线程统计io使用信息
    // flag_dump_uid代表storaged -u,flag_dump_task代码表stoaged -t
    // 但我们从代码中可以看出,-u和-t是一样的,都是按uid统计io信息
    if (flag_dump_uid || flag_dump_task) {
        vector uid_io;
        binder::Status status = storaged_service->dumpUids(&uid_io);
        if (!status.isOk() || uid_io.size() == 0) {
            fprintf(stderr, "UID I/O info is not available.\n");
            return 0;
        }

        sort_running_uids_info(uid_io);
        log_console_running_uids_info(uid_io, flag_dump_task);
    }

    //storaged -p统计io性能数据
    if (flag_dump_perf) {
        vector perf_history;
        binder::Status status = storaged_service->dumpPerfHistory(&perf_history);
        if (!status.isOk() || perf_history.size() == 0) {
            fprintf(stderr, "I/O perf history is not available.\n");
            return 0;
        }

        log_console_perf_history(perf_history);
    }

    return 0;
}

init进程执行的是/system/bin/storaged命令,所以 执行if (flag_main_service)为ture的分支,在这个分支中,StoragedService::start()发布storaged service(android中的service概念,通过service list命令查看),StoragedPrivateService::start()发布storaged_pri service(android中的service概念,通过service list命令查看)。

下一篇文章讲解锁时,存储相关的流程。

你可能感兴趣的:(android,存储,android,存储)