三、sbin/recovery/服务流程-recovery.cpp main方法

本文详细分析了recovery.cppmain方法的执行流程,包括加载分区表、获取升级参数、执行升级命令等关键步骤,深入探讨了Android系统recovery模式下的启动和服务流程。

三、sbin/recovery/服务流程-recovery.cpp main方法

    本次将分析recovery.cpp main方法,其中会介绍一部分C++ 基础,话不多说,直接开始,我们都知道从bootloder引导分区后会判断misc的参数,如果是boot-recovery ,会驱动进入recovery模式,这部分后面会进行补充,暂时对主要流程进行二次分析

1、加载分区表

2、get_args

3、加载selinux

4、关于路径转换解析

5、执行传入参数命令

6、finish_recovery

 

那么首先其实跟system的启动相同,会执行内核的init.rc

etc/init.rc:

service recovery /sbin/recovery

   seclabel u:r:recovery:s0

直接去启动recovery服务,这个文件是编译在recovey/sbin下的可执行文件,我们开启main方法之旅

//argc和argv参数在用命令行编译程序时有用。main( int argc, char* argv[], char **env ) 中 
//第一个参数,int型的argc,为整型,用来统计程序运行时发送给main函数的命令行参数的个数
//第二个参数,char*型的argv[],为字符串数组,用来存放指向的字符串参数的指针数组
//首先我们看到mian,需要知道这两个参数传进来的是什么
int main(int argc, char **argv) {
  //所以一开始在这里加了打印出参数的内容,但是试了几次都没有看到last_log的输出,没有参数时不可能的,
  //所以应该这里应该是我们的print提前了,这里还没有定义log和log定向输出
  //int i;
  //for (i = 0; i < argc; i++){
  //printf("argc && argv we need know how much the argc argv\n");
  //printf("argv %d is %s\n", i, argv[i]);
  //}
  //从这里开始,定义log部分,从注释中也能够看出来
  // We don't have logcat yet under recovery; so we'll print error on screen and
  // log to stdout (which is redirected to recovery.log) as we used to do.
  android::base::InitLogging(argv, &UiLogger);

  // Take last pmsg contents and rewrite it to the current pmsg session.
  static const char filter[] = "recovery/";
  // Do we need to rotate?
  bool doRotate = false;

  __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logbasename, &doRotate);
  // Take action to refresh pmsg contents
  __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logrotate, &doRotate);

  //启动一个adbd,为了使用adb sideload命令,也就是如果我们用这个命令启动recovery sdcard升级,
  //那么其实是启动了sbin/adbd服务,如果我们直接在线升级的话 ,是用不到adbd服务的,所以参数里没有adbd
  if (argc == 2 && strcmp(argv[1], "--adbd") == 0) {
    minadbd_main();
    return 0;
  }
  // redirect_stdio should be called only in non-sideload mode. Otherwise
  // we may have two logger instances with different timestamps.
  // log的重定向 
  redirect_stdio(TEMPORARY_LOG_FILE);
  int i;
  //打印结果 argv 0 is /sbin/recovery, 目前暂时猜想传进来的只有recovery服务/sbin/recovery
  for (i = 0; i < argc; i++){
    printf("argc && argv we need know how much the argc argv\n");
    printf("argv %d is %s\n", i, argv[i]);
  }
  //打印出当前升级的时间
  printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
  //加载分区表 TODO 暂时知道输出了什么,具体的流程比较复杂,需要慢慢分析
  load_volume_table();
  //判断是不是可以加载cache 和 nvdata
  has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr;
  has_nvdata = volume_for_mount_point(NVDATA_ROOT) != nullptr;
  //初始化分区类型,不过这个方法在之前load_volume_table()方法中已经执行过了,所以这里只是再次确认
  //如果已经初始化,则跳过
  mt_init_partition_type();

 

1、加载分区表 load_volume_table();

补充说明:fstab类型  system/core/fs_mgr/include_fstab/fstab/fstab.h

//定义了一个链表,包含了三个元素,包含个数,每条信息所包含的内容recs,fstab表的名称
struct fstab {
    int num_entries;
    struct fstab_rec* recs;
    char* fstab_filename;
};

struct fstab_rec {
    char* blk_device;
    char* mount_point;
    char* fs_type;
    unsigned long flags;
    char* fs_options;
    int fs_mgr_flags;
    char* key_loc;
    char* key_dir;
    char* verity_loc;
    long long length;
    char* label;
    int partnum;
    int swap_prio;
    int max_comp_streams;
    unsigned int zram_size;
    uint64_t reserved_size;
    unsigned int file_contents_mode;
    unsigned int file_names_mode;
    unsigned int erase_blk_size;
    unsigned int logical_blk_size;
    char* sysfs_path;
};

 

bootable/recovery/roots/cpp load_volume_table方法

//注意下这个时全局静态的fstab,因为别的方法也会调用到
static struct fstab* fstab = nullptr;
//在变量定义前加extern关键字表示声明一个变量但不定义它 。它表示"这只是一个声明,它的定义在别的地方",关键字extern,它表示变量是在文件以外定义的,或在文件后面部分才定义.
extern struct selabel_handle* sehandle;

void load_volume_table() {
  //根据基础的etc/recovery.fstab生成fstab
  fstab = fs_mgr_read_fstab_default();
  if (!fstab) {
    LOG(ERROR) << "Failed to read default fstab";
    return;
  }
  //追加条目/tmp ramdisk ramdisk 0
  int ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk");
  if (ret == -1) {
    LOG(ERROR) << "Failed to add /tmp entry to fstab";
    fs_mgr_free_fstab(fstab);
    fstab = nullptr;
    return;
  }
  //追加条目sdcard 
  ///sdcard vfat /dev/block/mmcblk1p1 0 
  ///sdcard_dev2 vfat /dev/block/platform/bootdevice/by-name/intsd 0
  ret = mt_load_volume_table(fstab);
  if (ret < 0 ) {
    LOG(ERROR) << "mt_load_volume_table fail to add entry to fstab";
    fs_mgr_free_fstab(fstab);
    fstab = NULL;
    return;
  }

  mt_ensure_dev_ready("/misc");
  mt_ensure_dev_ready("/cache");
  mt_fstab_translation_NAND(fstab);
  printf("recovery filesystem table\n");
  printf("=========================\n");
  //遍历出fstab并打印,看log结果中 length为0 为什么都为0?
  //这里会遍历fstab,打印出 编号 挂载点 文件系统类型 块设备 长度
  for (int i = 0; i < fstab->num_entries; ++i) {
    const Volume* v = &fstab->recs[i];
    printf("  %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, v->blk_device, v->length);
  }
  printf("\n");
}

 

system/core/fs_mgr/fs_mgr_fstab.cpp  fs_mgr_read_fstab_default()方法

/*
 * load
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值