Android启动之后,系统的分区工作已经完成,但是分区是在哪来进行的?

一个大的系统启动不可能每个分区都要去手动挂载,添加,肯定有一个自动加载的工作,Android 本身也是一个Linux系统,我们先从Linux的分区开始了解。


Linux系统分区

linux 开机时会 自动加载分区,只不过要先配置好分区文件fstab (/etc/fstab),如下:
  # /etc/fstab  /dev/hda9 swap swap defaults 0 0  /dev/hda1 / ext2 defaults 1 1  /dev/hda5 /home ext2 defaults 1 1  /dev/hda6 /usr ext2 defaults 1 1  /dev/hda7 /usr/local ext2 defaults 1 1  /dev/hda8 /var ext2 defaults 1 1  /dev/hdb /cdrom iso9660 noauto,user 0 0  none /proc proc defaults 0 0  none /dev/pts devpts gid=5,mode=620 0 0

fstab文件的作用



   文件/etc/fstab存放的是系统中的文件系统信息。当正确的设置了该文件,则可以通过"mount /directoryname"命令来加载
一个文件系统,每种文件系统都对应一个独立的行,每行中的字段都有空格或tab键分开。同时fsck、 mount、umount的等命令都
利用该程序。


fstab文件格式



  下面是/etc/fatab文件的一个示例行:


  fs_spec fs_file fs_type fs_options fs_dump fs_pass


  /dev/hda1 / ext2 defaults 1 1


  fs_spec - 该字段定义希望加载的文件系统所在的设备或远程文件系统,对于一般的本地块设备情况来说:IDE设备一般描述为
/dev/hdaXN,X是IDE设备通道 (a, b, or c),N代表分区号;SCSI设备一描述为/dev/sdaXN。对于NFS情况,格式一般为:
例 如:`knuth.aeb.nl:/'。对于procfs,使用`proc'来定义。


  fs_file - 该字段描述希望的文件系统加载的目录点,对于swap设备,该字段为none;对于加载目录名包含空格的情况,用40来
表示空格。


  fs_type - 定义了该设备上的文件系统,一般常见的文件类型为ext2 (linux设备的常用文件类型)、vfat(Windows系统的fat32格
式)、NTFS、iso9600等。


  fs_options - 指定加载该设备的文件系统是需要使用的特定参数选项,多个参数是由逗号分隔开来。对于大多数系统使用"defaults"
就可以满足需要。其他常见的选项包括:


选项含义



  ro 以只读模式加载该文件系统


  sync 不对该设备的写操作进行缓冲处理,这可以防止在非正常关机时情况下破坏文件系统,但是却降低了计算机速度


  user 允许普通用户加载该文件系统


  quota 强制在该文件系统上进行磁盘定额限制


  noauto 不再使用mount -a命令(例如系统启动时)加载该文件系统


  fs_dump - 该选项被"dump"命令使用来检查一个文件系统应该以多快频率进行转储,若不需要转储就设置该字段为0


  fs_pass - 该字段被fsck命令用来决定在启动时需要被扫描的文件系统的顺序,根文件系统"/"对应该字段的值应该为1,其他文件系统应该为2。若该文件系统无需在启动时扫描则设置该字段为0

Android系统分区文件

android系统也有自己的系统分区文件fstab.${ro.hardware} ,一般为fstab.muji , fstab.monet, ..... 例如:fstab.muji文件
# Android fstab file.#<src>                                                  <mnt_point>         <type>    <mnt_flags>                                          <fs_mgr_flags># The filesystem that contains the filesystem checker binary (typically /system) cannot# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK/dev/block/platform/mstar_mci.0/by-name/system          /system             ext4      ro                                                    wait/dev/block/platform/mstar_mci.0/by-name/cache           /cache              ext4      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/platform/mstar_mci.0/by-name/userdata        /data               ext4      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/platform/mstar_mci.0/by-name/tvservice       /tvservice          ext4      ro                                                    wait/dev/block/platform/mstar_mci.0/by-name/tvconfig        /tvconfig           ext4      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/platform/mstar_mci.0/by-name/tvdatabase      /tvdatabase         ext4      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/platform/mstar_mci.0/by-name/tvcustomer      /tvcustomer         ext4      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/platform/mstar_mci.0/by-name/usersdcard      /usersdcard         vfat      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/platform/mstar_mci.0/by-name/factory         /factory            ext4      noatime,nosuid,nodev                                  wait,block_validity,nodiscard,data=ordered,journal_checksum/dev/block/mmcblk0boot0                                 /boot1              emmc      defaults                                              defaults/dev/block/mmcblk0boot1                                 /boot2              emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/MBOOT           /MBOOT              emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/MPOOL           /MPOOL              emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/misc            /misc               emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/recovery        /recovery           emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/boot            /boot               emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/tee             /tee                emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/RTPM            /RTPM               emmc      defaults                                              defaults/dev/block/platform/mstar_mci.0/by-name/dtb             /dtb                emmc      defaults                                              defaults
这里描述了系统所有分区位置,挂载点,类型,一些挂载参数

分区启动方式

从源码看,目前发现有两处地方有进行分区的动作:1. init脚本 ; 2. vold服务程序 3. fs_mgr

init脚本

on fs      mkdir /tvservice      mkdir /tvconfig      mkdir /tvdatabase      mkdir /tvcustomer      mount_all /fstab.monet  
mount_all 命令在system\core\init\keywords.h中注册
KEYWORD(mount_all,   COMMAND, 1, do_mount_all)
接着会调用init进程的do_mount_all (builtins.c文件)
/* * This function might request a reboot, in which case it will * not return. */int do_mount_all(int nargs, char **args){    pid_t pid;    int ret = -1;    int child_ret = -1;    int status;    const char *prop;    struct fstab *fstab;    if (nargs != 2) {        return -1;    }    /*     * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and     * do the call in the child to provide protection to the main init     * process if anything goes wrong (crash or memory leak), and wait for     * the child to finish in the parent.     */    pid = fork();    if (pid > 0) {        /* Parent.  Wait for the child to return */        int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));        if (wp_ret < 0) {            /* Unexpected error code. We will continue anyway. */            NOTICE("waitpid failed rc=%d, errno=%d\n", wp_ret, errno);        }        if (WIFEXITED(status)) {            ret = WEXITSTATUS(status);        } else {            ret = -1;        }    } else if (pid == 0) {        /* child, call fs_mgr_mount_all() */        klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */        fstab = fs_mgr_read_fstab(args[1]);        child_ret = fs_mgr_mount_all(fstab);        fs_mgr_free_fstab(fstab);        if (child_ret == -1) {            ERROR("fs_mgr_mount_all returned an error\n");        }        _exit(child_ret);    } else {        /* fork failed, return an error */        return -1;    }    ......    return ret;}
fs_mgr_read_fstab完整fstab.muji 的解析,fs_mgr_mount_all完成所有目录的挂载

vold服务

该服务主程序源码位于system\vold\main.cpp,通过函数process_config 调用fs_mgr_read_fstab完成文件的解析,注册的CommandListener在接收到mountall指令之后 完成所有分区注册:
int CommandListener::StorageCmd::runCommand(SocketClient *cli,                                                      int argc, char **argv) {    /* Guarantied to be initialized by vold's main() before the CommandListener is active */    extern struct fstab *fstab;    dumpArgs(argc, argv, -1);    if (argc < 2) {        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);        return 0;    }    if (!strcmp(argv[1], "mountall")) {        if (argc != 2) {            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: mountall", false);            return 0;        }        fs_mgr_mount_all(fstab);        cli->sendMsg(ResponseCode::CommandOkay, "Mountall ran successfully", false);        return 0;    }    if (!strcmp(argv[1], "users")) {        DIR *dir;        struct dirent *de;        if (argc < 3) {            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument: user <mountpoint>", false);            return 0;        }        if (!(dir = opendir("/proc"))) {            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true);            return 0;        }        while ((de = readdir(dir))) {            int pid = Process::getPid(de->d_name);            if (pid < 0) {                continue;            }            char processName[255];            Process::getProcessName(pid, processName, sizeof(processName));            if (Process::checkFileDescriptorSymLinks(pid, argv[2]) ||                Process::checkFileMaps(pid, argv[2]) ||                Process::checkSymLink(pid, argv[2], "cwd") ||                Process::checkSymLink(pid, argv[2], "root") ||                Process::checkSymLink(pid, argv[2], "exe")) {                char msg[1024];                snprintf(msg, sizeof(msg), "%d %s", pid, processName);                cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false);            }        }        closedir(dir);        cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false);    } else {        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);    }    return 0;}
我们可以看到在fs_mgr_mount_all(fstab);之后所有客户端。

fs_mgr 进程

该服务源码位于system\core\fs_mgr\fs_mgr_main.c,该模块是解析分区文件,并完成挂载任务的最终工作者。


更多相关文章

  1. Android中Handler与Message的简单实例
  2. Android(安卓)根文件系统启动过程(init进程 详细分析)
  3. 分析Android(安卓)根文件系统启动过程(init守护进程分析)
  4. Android中Java反射技术的使用示例
  5. 挂载android只读文件系统为可读写
  6. Android的SMS短消息格式和主要字段
  7. android linux 基础知识总结
  8. android linux 最全的基础知识总结
  9. Android根据 uri 获得文件真实路径

随机推荐

  1. Android(安卓)View的属性
  2. android google地图定位开发,且可以自由移
  3. Android(安卓)技术专题系列之十三 -- 与PC
  4. Android(安卓)安全架构及权限控制机制剖
  5. android 电容屏(二):驱动调试之基本概念篇
  6. Android(安卓)SDK 2.2 和ADT插件下载
  7. 自定义ListView中的分割线
  8. android 的各种manager
  9. android 开发 解码gif图片,获取每帧bitmap
  10. Android中显示在线PDF