精华内容
下载资源
问答
  • 我试了下没问题:~$ddif=/dev/zeroof=test.imgcount=200Miflag=count_bytes记录了409600+0的读入记录了409600+0的写出209715200bytes(210MB,200MiB)copied,1.30313s,161MB/s~$mkfs.ext4test.img-Enodiscardmke2fs...

    我试了下没问题:

    ~ $ dd if=/dev/zero of=test.img count=200M iflag=count_bytes

    记录了409600+0 的读入

    记录了409600+0 的写出

    209715200 bytes (210 MB, 200 MiB) copied, 1.30313 s, 161 MB/s

    ~ $ mkfs.ext4 test.img -E nodiscard

    mke2fs 1.45.4 (23-Sep-2019)

    创建含有 204800 个块(每块 1k)和 51200 个inode的文件系统

    文件系统UUID:4473a3aa-1671-4e4b-adea-62f10d99c0ac

    超级块的备份存储于下列块:

    8193, 24577, 40961, 57345, 73729

    正在分配组表: 完成

    正在写入inode表: 完成

    创建日志(4096 个块)完成

    写入超级块和文件系统账户统计信息: 已完成

    ~ $ guestmount -a test.img -m /dev/sda mnt

    ~ $ cp -R --sparse=never /boot mnt/

    cp: 无法访问 '/boot/lost+found': 权限不够

    cp: 无法打开'/boot/luks-header-backup.img' 读取数据: 权限不够

    ~ $ ls -R mnt/boot

    mnt/boot:

    efi/                          initramfs-linux-lts-fallback.img  initramfs-linux-zen.img  refind_linux.conf   vmlinuz-linux-lts

    initramfs-linux-fallback.img  initramfs-linux-lts.img           intel-ucode.img          refind_linux.conf~  vmlinuz-linux-zen

    initramfs-linux.img           initramfs-linux-zen-fallback.img  lost+found/              vmlinuz-linux

    mnt/boot/efi:

    mnt/boot/lost+found:

    ~ $

    你也可以试试用guestfish往里拷数据,不通过fuse mount。

    【 在 hyperisnice 的大作中提到: 】

    : 试了 非sudo会报下面的错误

    : cp: cannot open '/boot/vmlinuz' for reading: Permission denied

    : 非root用户试了没法 拷贝/boot/vmlinuz 文件.

    : ...................

    展开全文
  • 首先,参考... 通过上面这个链接,做一个镜像出来。 // 1. 制作一个镜像文件,里面包含200M左右的空间 sudo dd if=/dev/zero of=sbc7816.img bs=1M count=200 // 2 . 加载这个镜像 ...
    • 首先,参考http://www.cnblogs.com/chenfulin5/p/6649801.html

        通过上面这个链接,做一个镜像出来。
        // 1.  制作一个镜像文件,里面包含200M左右的空间
        sudo  dd  if=/dev/zero of=sbc7816.img   bs=1M  count=200
        
        // 2 . 加载这个镜像
        sbc_7816_test@aplex:~/image$ sudo losetup -f --show sbc7816.img 
        //  显示加载的节点
        /dev/loop0
    
        // 3. 和平常的块设备一样 用fdisk 进行分区
        fdisk  /dev/loop0
        //  具体分区细节请参考上面的链接
    
        // 4. 同步
        sudo kpartx -av /dev/loop0
    
        // 5. 格式化
        sudo mkfs.vfat    -n "boot" -F 16  /dev/mapper/loop0p1
        sudo mkfs.ext3   -L "rootfs"          /dev/mapper/loop0p2 
        
        //  6. 挂载复制
        sudo mount /dev/mapper/loop0p1   p1
        sudo mount /dev/mapper/loop0p2   p2
    
        // 7. 复制你的镜像文件到对应的分区
        sudo cp boot/*  p1  -rf
        sudo cp rootfs/* p2 -rf
        sync
    
        // 8 解除挂载,映射
        sudo umount p1 p2
        sudo  kpartx -d /dev/loop0
        sudo  losetup -d /dev/loop0
    • 将制作好的镜像文件放到 windows

        利用 windisk32 工具进行直接对SD卡进行烧写
        下载地址:https://sourceforge.net/projects/win32diskimager/files/latest/download
        安装完成后,打开
    ![](http://images2017.cnblogs.com/blog/991711/201709/991711-20170926141716557-624733846.png)

    转载于:https://www.cnblogs.com/chenfulin5/p/7596564.html

    展开全文
  • Windows下查看Linuxext4文件系统

    万次阅读 2014-07-25 19:17:04
    7下查看Linux中的ext4文件系统,我是通过LinuxReader实现。 LinuxReader 是一款 免费软件 ,下载地址:  绿色版:http://www.piaodown.com/soft/72871.htm,下载后解压缩之后即可用。  安装版:...

        本人机子上装的是Windows 7 & CentOS 6.5双系统,前段时间在博客中记录过文章:Linux通过ntfs-3g挂载ntfs文件系统,而Windows 7下查看Linux中的ext4文件系统,我是通过LinuxReader实现。LinuxReader是一款免费软件,下载地址:

          绿色版:http://www.piaodown.com/soft/72871.htm,下载后解压缩之后即可用。

          安装版:http://www.diskinternals.com/linux-reader/,下载后需要完全安装,个人感觉安装版更稳定和流畅,推荐使用这个。

          LinuxReader只能通过只读方式查看ext4中的文件,不能修改和添加文件,可以将Linux中的文件提取到Windows系统中

          LinuxReader V1.9.3.0首界面:  


            LinuxReader V1.9.3.0浏览界面:

     

    展开全文
  • 如何制作Ext4文件系统镜像

    千次阅读 2016-07-14 18:52:51
    编译Android源码最后是使用make_ext4生成 Ext4镜像+签名(更新:合理使用make_ext4参数是不会导致添加签名的),如果需要纯Ext4镜像,那么需要再去掉签名,使用simg2img。这个两个工具都是在编译Android源码时编译出来...

    如何制作Ext4文件系统镜像

    Android中system.img的两种格式及其相互转换方法

    搞Android的同学经常会接触到system.img。但是该文件经常以两种格式出现:raw和sparse。
    一种是raw ext4 image,即经常说的raw image,使用file观察它: 其特点是完整的ext4分区镜像(包含很多全零的无效填充区),可以直接使用mount进行挂载,因此比较大(一般1G左右)。
    $ file system.img
    system.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)
    信息非常明确了。
    另一种是sparse ext4 image,即经常说的simg,使用file观察它:
    $ file system.img
    system.img: data
    就是说是一个非常普通的dat文件。由于它将raw ext4进行稀疏描述,因此尺寸比较小(没有全零的无效填充区,一般在300到500M之间)。
    android本身提供了源代码工具在两者之间转换,源代码位于:
    system/core/libsparse/simg2img.c // 将sparse image转换为raw image;
    system/core/libsparse/img2simg.c // 将raw image转换为sparse image;

    如果完整的进行过一次Android的编译,默认会将simg2img当作主机工具编译出来,放在out/host/linux-x86/bin/simg2img处。 但默认是不会编译img2simg的,我们可以手工进行编译:
    $ . build/envsetup.sh
    $ lunch aosp_hammerhead-userdebug
    $ make img2simg_host

    这样就会编译出out/host/linux-x86/bin/img2simg。 如果要将system.raw.img转换为system.simg: $ img2simg system.raw.img system.simg

    编译Android源码最后是使用make_ext4生成 Ext4镜像+签名(更新:合理使用make_ext4参数是不会导致添加签名的),如果需要纯Ext4镜像,那么需要再去掉签名,使用simg2img。这个两个工具都是在编译Android源码时编译出来的,如果没有Android源码编译环境,当然也可以使用Ubuntu社区已经整理好的工具集android-tools-fsutils,该工具集文件列表如下:(来自android-tools-fsutils/filelist)

    /usr/bin/ext2simg
    /usr/bin/ext4fixup
    /usr/bin/img2simg
    /usr/bin/make_ext4fs
    /usr/bin/mkuserimg
    /usr/bin/simg2img
    /usr/bin/simg2simg
    /usr/bin/simg_dump
    /usr/bin/test_ext4fixup
    

    工具集安装方法:

    sudo apt-get install android-tools-fsutils

        1

        1

    制作Ext4文件系统镜像:

    # 创建测试目录
    mkdir /tmp/ext4 && cd /tmp/ext4 &&
    mkdir test test_mount &&
    echo "Hello Ext4" > test/HelloExt4.txt &&

    # 生成名为test.ext4的Ext4镜像
    make_ext4fs -l 512M test.ext4 test &&

    # 挂载test.ext4到test_mount测试
    mount -t ext4 -o loop test.ext4 test_mount &&
    ls test_mount || echo "Error!"


    一、在(yourAndroid code path)/out/  目录里查找这个工具 

    unyaffs: 用于解压system.img  

    mkyaffs2image: 用于打包system.img

    呵呵, find 命令肯定会吧?  find  out/   -name mkyaffs2image
    找到了后,记住这个目录. 我的是(codePATH)/out/host/linux-x86/bin/

    1.在任意文件夹下面建立一个system文件夹,我的是在home/changjiang/下面建的,这个是用来存放你解压system.img出来的文件,然后将找到的两个工具 unyaffs、mkyaffs2image拷贝到/changjiang/home/system

    2.将编译出来的system.img或者下载的system.img复制到system文件夹中。

    3.在终端中输入如下命令操作(/home/changjiang/替换成自己电脑中的路径,你的不是我的)
    cd /home/changjiang/system
    ./unyaffs /home/changjiang/system/system.img(用unyaffs命令解压system.img),解压出来的有各种应用,库等等,你可以修改或者替换


    二、重新打包system.img,虽然我不知道为什么要这样做,但是我知道这样做是可以的.

    呵呵,linux没有不可能的事情.朝鲜的  红星操作系统就是例子.
    具体办法是
     system/  这个目录,这个目录就是用来生成system.img 的.

     mkyaffs2image    system/   system.img

     

    在Ubuntu中第一次使用mkyaffs2image命令时,会提示

    mkyaffs2image:找不到命令

    还需要安装mkyaffs2image

    http://code.google.com/p/fatplus/downloads/detail?name=yaffs2-source.tar&can=2&q=

    下载yaffs2-source.tar 

    解压后,进入utils文件夹,然后make

    将make之后生成的mkyaffs2image文件拷贝到/usr/bin目录下

    $ su
    # cp mkyaffs2image /usr/bin/
    # chmod 777 /usr/bin/mkyaffs2image

    之后

    $ mkyaffs2image 
    mkyaffs2image: image building tool for YAFFS2 built Jan  6 2012
    usage: mkyaffs2image dir image_file [convert]
               dir        the directory tree to be converted
               image_file the output file to hold the image
               'convert'  produce a big-endian image from a little-endian machine

    表明安装成功,同时也可以看到该命令的用法

    mkyaffs2image dir image_file
    例如:

    mkyaffs2image am1808-fs am1808-fs.yaffs//创建jffs2文件


    搞Android的同学经常会接触到system.img。但是该文件经常以两种格式出现:raw和sparse。
    一种是raw ext4 image,即经常说的raw image,使用file观察它: 其特点是完整的ext4分区镜像(包含很多全零的无效填充区),可以直接使用mount进行挂载,因此比较大(一般1G左右)。

    $ file system.img
    system.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)
    信息非常明确了。
    另一种是sparse ext4 image,即经常说的simg,使用file观察它:
    $ file system.img
    system.img: data
    就是说是一个非常普通的dat文件。由于它将raw ext4进行稀疏描述,因此尺寸比较小(没有全零的无效填充区,一般在300到500M之间)。
    android本身提供了源代码工具在两者之间转换,源代码位于:
    system/core/libsparse/simg2img.c // 将sparse image转换为raw image;
    system/core/libsparse/img2simg.c // 将raw image转换为sparse image;

    如果完整的进行过一次Android的编译,默认会将simg2img当作主机工具编译出来,放在out/host/linux-x86/bin/simg2img处。 但默认是不会编译img2simg的,我们可以手工进行编译:
    $ . build/envsetup.sh
    $ lunch aosp_hammerhead-userdebug
    $ make img2simg_host

    这样就会编译出out/host/linux-x86/bin/img2simg。 如果要将system.raw.img转换为system.simg: $ img2simg system.raw.img system.simg
    为了方便没有源代码的同学,这里提供img2simg的下载路径: http://download.csdn.net/detail/howellzhu/8399215
    对于simg2img,到处都可以找到了,还有windows版本的,这里就不提供了。 使用方法:
    $ simg2img  
    $ img2simg   []



    1、解压system.img

    先用file命令查看system.img的文件类型

    file system.img

     system.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (needs journal recovery) (extents) (large files)

    看到没 ext4 filesystem data

    那好办,采用挂载分区的方式来打开system.img文件

    mount -t ext4 -o loop system.img  systemimg    //此命令的意思将system.img镜像文件挂载到systemimg目录

    cd systemimg

    Android标准的文件结构就出来了,里面可以“随意”定制

    2、重新打包生成system.img

    打包命令:

    ./make_ext4fs -l 1024M -s -a system system_new.img systemimg

    参数解析:1024M代表你要打包的system.img大小,这个值可以参考挂载前system.img的大小

    "-a system",是指这个img用于android系统,挂载点是/system,使用这个参数,make_ext4fs会根据private/android_filesystem_config.h里定义好的权限来给文件夹里的所有文件重新设置权限,如果你刷机以后发现有文件权限不对,可以手工修改android_filesystem_config.h来添加权限,重新编译make_ext4fs,也可以不使用 “-a system”参数,这样就会使用文件的默认权限。

    system_new.img代表新生成的img

    systemimg就是上面挂载后的目录

    一般很多人认为这样生成的system_new.img就可以用了,其实不然

    再次用file命令查看文件类型

    file system_new.img

     system_new.img: data

    跟之前的输出截然不同,这显然不是ext4文件类型,啥情况???

    方法就是继续使用simg2img工具将其转换成真正的ext4文件

    ./simg2img system_new.img system_out.img

    得到system_out.img

    file system_out.img

    system_out.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)

    怎么样?这次得到的img就是ext4了吧?ok,那么这个system_out.img就是我们重新打包生成的img了,这就可以烧到手机里面看看效果了。。。

    PS:上面提到的make_ext4fs simg2img等工具在android环境的out/host/linux-x86/bin目录下。

    上文说到 通过remount的方式来修改/system/bin 下的权限;

    还有一种办法就是在打包system.img时就设置好权限,而这种办法就是通过修改:make.ext4fs


    system/core/include/private/android_filesystem_config.h

             +    { 00777, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },

         编译make.ext4fs:

    # mmm system/extras/ext4_utils/

           #mmm system/core/

         再打包 ------- ,然后全部重新烧录:可以看到权限被修改过来。



    参考转载:http://blog.csdn.net/myxmu/article/details/8583470

    make_ext4fs用于Android平台上制作ext4文件系统的镜像。用法举例:

    make_ext4fs -l 512M -s -a system system.ext4img system

    之后再使用simg2img制作镜像。

    有一个问题是,使用这样制作的镜像,system分区文件的权限都是预定的,即使先修改system目录文件权限后在制作镜像,烧入设备后,其权限仍未改变。关键问题在make_ext4fs工具,在制作ext4fs时更改了权限,其依据为system/core/private/android_ilesystem_config.h所定义的权限。

    查询make_ext4fs的参数含义,可以了解到这一点。


    -l 512M"是分区大小,i9100的system分区是512M;
    -s就是生成ext4的S模式制作;
    "-a system",是指这个img用于android系统,挂载点是/system,使用这个参数,make_ext4fs会根据private/android_filesystem_config.h里定义好的权限来给文件夹里的所有文件重新设置权限,如果你刷机以后发现有文件权限不对,可以手工修改android_filesystem_config.h来添加权限,重新编译make_ext4fs,也可以不使用 “-a system”参数,这样就会使用文件的默认权限。

    如果不使用-a参数,则可。

    今天偶尔看到有人问起,如何解包打包安卓的各类 img 文件。下面介绍下

    首先可以去 https://android.googlesource.com/platform/system/extras下载工具源代码

    $ git clone https://android.googlesource.com/platform/system/extras /your/path
    

    checkout 你需要的版本,譬如 android-5.1.1_r13

    $ cd /your/path/extras
    $ git checkout android-5.1.1_r13
    

    编译 simg2img,这里你需要 gcc 工具,linux 用户基本都由现成的,mac 用户通过 homebrew 安装一个去

    $ cd /your/path/extras/ext4_utils
    $ gcc -o simg2img -lz sparse_crc32.c simg2img.c
    $ gcc -o make_ext4fs -lz make_ext4fs_main.c make_ext4fs.c ext4fixup.c ext4_utils.c allocate.c backed_block.c output_file.c contents.c extent.c indirect.c uuid.c sha1.c sparse_crc32.c wipe.c
    

    当前目录会生成 simg2img 与 make_ext4fs 两进制文件

    下面解包开始,以 system.img 为例

    $ ./simg2img system.img system.ext4
    

    随后,可以直接挂载,需要 root 权限

    # mkdir /your/path/system-data
    # mount -t ext4 -o loop system.ext4 /your/path/system-data
    

    打包的话,则是如此操作

    $ ./make_ext4fs -s -l 512M -a system system-data.img /your/path/system-data
    

    或者使用源代码中的脚本

    $ cd /your/path/extras
    $ PATH="$PATH:$(pwd)/ext4_utils/make_ext4fs" ./ext4_utils/mkuserimg.sh -s /your/path/system-data system-data.img ext4 /tmp 512M
    

    最后转换下

    $ ./simg2img system-data.img system.img
    

    OK,你可以刷入你的手机了,Good luck!



    Super block

    只是在ext3的基础上扩展了一些字段,可以支持更大的硬盘和更大的文件。如:s_blocks_count  修改为s_blocks_count_lo和s_blocks_count_hi

    结构体如下:

    1. /*  
    2.  *Structure of the super block  
    3.  */  
    4. struct ext4_super_block {  
    5. /*00*/ __le32  s_inodes_count;         /* Inodes count文件系统中inode的总数*/  
    6.        __le32  s_blocks_count_lo;      /* Blocks count文件系统中块的总数*/  
    7.        __le32  s_r_blocks_count_lo;    /* Reserved blocks count保留块的总数*/  
    8.        __le32  s_free_blocks_count_lo; /*Free blocks count未使用的块的总数(包括保留块)*/  
    9. /*10*/ __le32  s_free_inodes_count;    /* Free inodes count未使用的inode的总数*/  
    10.        __le32  s_first_data_block;     /* First Data Block第一块块ID,在小于1KB的文件系统中为0,大于1KB的文件系统中为1*/  
    11.        __le32  s_log_block_size;       /* Block size用以计算块的大小(1024算术左移该值即为块大小)(0=1K, 1=2K, 2=4K) */  
    12.        __le32  s_obso_log_frag_size;   /* Obsoleted fragment size用以计算段大小(为正则1024算术左移该值,否则右移)*/  
    13. /*20*/ __le32  s_blocks_per_group;     /* # Blocks per group每个块组中块的总数*/  
    14.        __le32  s_obso_frags_per_group; /*Obsoleted fragments per group每个块组中段的总数*/  
    15.        __le32  s_inodes_per_group;     /* # Inodes per group每个块组中inode的总数*/  
    16.        __le32  s_mtime;                /* Mount time POSIX中定义的文件系统装载时间*/  
    17. /*30*/ __le32  s_wtime;                /* Write time POSIX中定义的文件系统最近被写入的时间*/  
    18.        __le16  s_mnt_count;            /* Mount count最近一次完整校验后被装载的次数*/  
    19.        __le16  s_max_mnt_count;        /* Maximal mount count在进行完整校验前还能被装载的次数*/  
    20.        __le16  s_magic;                /* Magic signature文件系统标志*/  
    21.        __le16  s_state;                /* File system state文件系统的状态*/  
    22.        __le16  s_errors;               /* Behaviour when detectingerrors文件系统发生错误时驱动程序应该执行的操作*/  
    23.        __le16  s_minor_rev_level;      /* minor revision level局部修订级别*/  
    24. /*40*/ __le32  s_lastcheck;            /* time of last check POSIX中定义的文件系统最近一次检查的时间*/  
    25.        __le32  s_checkinterval;        /* max. time between checks POSIX中定义的文件系统最近检查的最大时间间隔*/  
    26.        __le32  s_creator_os;           /* OS生成该文件系统的操作系统*/  
    27.        __le32  s_rev_level;            /* Revision level修订级别*/  
    28. /*50*/ __le16  s_def_resuid;           /* Default uid for reserved blocks报留块的默认用户ID */  
    29.        __le16  s_def_resgid;           /* Default gid for reserved blocks保留块的默认组ID */  
    30.        /*  
    31.         * These fields are for EXT4_DYNAMIC_REV superblocks only.  
    32.         *  
    33.         * Note: the difference between the compatible feature set and  
    34.         * the incompatible feature set is that if there is a bit set  
    35.         * in the incompatible feature set that the kernel doesn't  
    36.         * know about, it should refuse to mount the filesystem.  
    37.         *  
    38.         * e2fsck's requirements are more strict; if it doesn't know  
    39.         * about a feature in either the compatible or incompatible  
    40.         * feature set, it must abort and not try to meddle with  
    41.         * things it doesn't understand...  
    42.         */  
    43.        __le32  s_first_ino;            /* First non-reserved inode标准文件的第一个可用inode的索引(非动态为11)*/  
    44.        __le16  s_inode_size;           /* size of inode structure inode结构的大小(非动态为128)*/  
    45.        __le16  s_block_group_nr;       /* block group # of this superblock保存此超级块的块组号*/  
    46.        __le32  s_feature_compat;       /* compatible feature set兼容特性掩码*/  
    47. /*60*/ __le32  s_feature_incompat;     /* incompatible feature set不兼容特性掩码*/  
    48.        __le32  s_feature_ro_compat;    /* readonly-compatible feature set只读特性掩码*/  
    49. /*68*/ __u8    s_uuid[16];             /* 128-bit uuid for volume卷ID,应尽可能使每个文件系统的格式唯一*/  
    50. /*78*/ char    s_volume_name[16];      /* volume name卷名(只能为ISO-Latin-1字符集,以'\0'结束)*/  
    51. /*88*/ char    s_last_mounted[64];     /* directory where last mounted最近被安装的目录*/  
    52. /*C8*/ __le32  s_algorithm_usage_bitmap;/* For compression文件系统采用的压缩算法*/  
    53.        /*  
    54.         * Performance hints.  Directorypreallocation should only  
    55.         * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.  
    56.         */  
    57.        __u8    s_prealloc_blocks;      /* Nr of blocks to try to preallocate预分配的块数*/  
    58.        __u8   s_prealloc_dir_blocks;  /* Nr topreallocate for dirs给目录预分配的块数*/  
    59.        __le16 s_reserved_gdt_blocks;  /* Pergroup desc for online growth */  
    60.        /*  
    61.         * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.  
    62.         */  
    63. /*D0*/ __u8    s_journal_uuid[16];     /* uuid of journal superblock日志超级块的卷ID */  
    64. /*E0*/ __le32  s_journal_inum;         /* inode number of journal file日志文件的inode数目*/  
    65.        __le32  s_journal_dev;          /* device number of journal file日志文件的设备数*/  
    66.        __le32  s_last_orphan;          /* start of list of inodes to delete要删除的inode列表的起始位置*/  
    67.        __le32  s_hash_seed[4];         /* HTREE hash seed HTREE散列种子*/  
    68.        __u8    s_def_hash_version;     /* Default hash version to use默认使用的散列函数*/  
    69.        __u8    s_jnl_backup_type;  
    70.        __le16  s_desc_size;            /* size of group descriptor */  
    71. /*100*/ __le32  s_default_mount_opts;  
    72.        __le32  s_first_meta_bg;        /* First metablock block group块组的第一个元块*/  
    73.         __le32 s_mkfs_time;            /* Whenthe filesystem was created */  
    74.        __le32  s_jnl_blocks[17];       /* Backup of the journal inode */  
    75.        /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */  
    76. /*150*/ __le32  s_blocks_count_hi;      /* Blocks count */  
    77.        __le32  s_r_blocks_count_hi;    /* Reserved blocks count */  
    78.        __le32  s_free_blocks_count_hi; /*Free blocks count */  
    79.        __le16  s_min_extra_isize;      /* All inodes have at least # bytes */  
    80.        __le16  s_want_extra_isize;     /* New inodes should reserve # bytes */  
    81.        __le32  s_flags;                /* Miscellaneous flags */  
    82.        __le16  s_raid_stride;          /* RAID stride */  
    83.        __le16 s_mmp_update_interval;  /* #seconds to wait in MMP checking */  
    84.         __le64 s_mmp_block;            /* Blockfor multi-mount protection */  
    85.        __le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/  
    86.        __u8   s_log_groups_per_flex;  /* FLEX_BGgroup size */  
    87.        __u8    s_reserved_char_pad;  
    88.        __le16  s_reserved_pad;  
    89.        __le64  s_kbytes_written;       /* nr of lifetime kilobytes written */  
    90.        __le32  s_snapshot_inum;        /* Inode number of active snapshot */  
    91.        __le32  s_snapshot_id;          /* sequential ID of active snapshot*/  
    92.        __le64  s_snapshot_r_blocks_count;/* reserved blocks for active  
    93.                                              snapshot's future use */  
    94.        __le32  s_snapshot_list;        /* inode number of the head of the  
    95.                                            on-disk snapshot list */  
    96. #define EXT4_S_ERR_START offsetof(structext4_super_block, s_error_count)  
    97.        __le32  s_error_count;          /* number of fs errors */  
    98.        __le32  s_first_error_time;     /* first time an error happened */  
    99.        __le32  s_first_error_ino;      /* inode involved in first error */  
    100.        __le64  s_first_error_block;    /* block involved of first error */  
    101.        __u8    s_first_error_func[32]; /*function where the error happened */  
    102.        __le32  s_first_error_line;     /* line number where error happened */  
    103.        __le32  s_last_error_time;      /* most recent time of an error */  
    104.        __le32  s_last_error_ino;       /* inode involved in last error */  
    105.        __le32  s_last_error_line;      /* line number where error happened */  
    106.        __le64  s_last_error_block;     /* block involved of last error */  
    107.        __u8   s_last_error_func[32];  /*function where the error happened */  
    108. #define EXT4_S_ERR_END offsetof(structext4_super_block, s_mount_opts)  
    109.        __u8    s_mount_opts[64];  
    110.        __le32  s_reserved[112];        /* Padding to the end of the block */  
    111. };  

    group descriptor

    块组描述信息。

    包含了blockbitmap、inode bitmap、inode table等存放的块地址。

    结构体如下:


    1. /*  
    2.  *Structure of a blocks group descriptor  
    3.  */  
    4. struct ext4_group_desc  
    5. {  
    6.        __le32  bg_block_bitmap_lo;     /* Blocks bitmap block块位图所在的第一个块的块ID */  
    7.        __le32  bg_inode_bitmap_lo;     /* Inodes bitmap block inode位图所在的第一个块的块ID */  
    8.        __le32  bg_inode_table_lo;      /* Inodes table block inode表所在的第一个块的块ID */  
    9.        __le16  bg_free_blocks_count_lo;/*Free blocks count块组中未使用的块数*/  
    10.        __le16  bg_free_inodes_count_lo;/*Free inodes count块组中未使用的inode数*/  
    11.        __le16 bg_used_dirs_count_lo;  /*Directories count块组分配的目录的inode数*/  
    12.        __le16  bg_flags;               /* EXT4_BG_flags (INODE_UNINIT,etc) */  
    13.        __u32   bg_reserved[2];         /* Likely block/inode bitmap checksum*/  
    14.        __le16  bg_itable_unused_lo;    /* Unused inodes count */  
    15.        __le16  bg_checksum;            /* crc16(sb_uuid+group+desc) */  
    16.        __le32  bg_block_bitmap_hi;     /* Blocks bitmap block MSB */  
    17.        __le32  bg_inode_bitmap_hi;     /* Inodes bitmap block MSB */  
    18.        __le32  bg_inode_table_hi;      /* Inodes table block MSB */  
    19.        __le16  bg_free_blocks_count_hi;/*Free blocks count MSB */  
    20.        __le16  bg_free_inodes_count_hi;/*Free inodes count MSB */  
    21.        __le16 bg_used_dirs_count_hi;  /*Directories count MSB */  
    22.        __le16  bg_itable_unused_hi;    /* Unused inodes count MSB */  
    23.        __u32   bg_reserved2[3];  
    24. };  

    inode

    保存了每个节点的信息。

    该节点的属性、所占的块地址。

    结构体如下:


    1. /*  
    2.  *Structure of an inode on the disk  
    3.  */  
    4. struct ext4_inode {  
    5.        __le16  i_mode;         /* File mode文件格式和访问权限*/  
    6.        __le16  i_uid;          /* Low 16 bits of Owner Uid文件所有者ID的低16位*/  
    7.        __le32  i_size_lo;      /* Size in bytes文件字节数*/  
    8.        __le32  i_atime;        /* Access time文件上次被访问的时间*/  
    9.        __le32  i_ctime;        /* Inode Change time文件创建时间*/  
    10.        __le32  i_mtime;        /* Modification time文件被修改的时间*/  
    11.        __le32  i_dtime;        /* Deletion Time文件被删除的时间(如果存在则为0)*/  
    12.        __le16  i_gid;          /* Low 16 bits of Group Id文件所有组ID的低16位*/  
    13.        __le16  i_links_count;  /* Links count此inode被连接的次数*/  
    14.        __le32  i_blocks_lo;    /* Blocks count文件已使用和保留的总块数(以512B为单位)*/  
    15.        __le32  i_flags;        /* File flags */  
    16.        union {  
    17.                 struct {  
    18.                         __le32  l_i_version;  
    19.                 } linux1;  
    20.                 struct {  
    21.                         __u32  h_i_translator;  
    22.                 } hurd1;  
    23.                 struct {  
    24.                         __u32  m_i_reserved1;  
    25.                 } masix1;  
    26.        } osd1;                         /*OS dependent 1 */  
    27.        __le32  i_block[EXT4_N_BLOCKS];/*Pointers to blocks定位存储文件的块的数组*/  
    28.        __le32  i_generation;   /* File version (for NFS) 用于NFS的文件版本*/  
    29.        __le32  i_file_acl_lo;  /* File ACL包含扩展属性的块号,老版本中为0*/  
    30.        __le32  i_size_high;  
    31.        __le32  i_obso_faddr;   /* Obsoleted fragment address */  
    32.        union {  
    33.                 struct {  
    34.                         __le16  l_i_blocks_high; /* were l_i_reserved1 */  
    35.                         __le16  l_i_file_acl_high;  
    36.                         __le16  l_i_uid_high;   /* these 2 fields */  
    37.                         __le16  l_i_gid_high;   /* were reserved2[0] */  
    38.                         __u32   l_i_reserved2;  
    39.                 } linux2;  
    40.                 struct {  
    41.                         __le16  h_i_reserved1;  /* Obsoleted fragment number/size which areremoved in ext4 */  
    42.                         __u16   h_i_mode_high;  
    43.                         __u16   h_i_uid_high;  
    44.                         __u16   h_i_gid_high;  
    45.                         __u32   h_i_author;  
    46.                 } hurd2;  
    47.                 struct {  
    48.                         __le16  h_i_reserved1;  /* Obsoleted fragment number/size which areremoved in ext4 */  
    49.                         __le16  m_i_file_acl_high;  
    50.                         __u32   m_i_reserved2[2];  
    51.                 } masix2;  
    52.        } osd2;                         /*OS dependent 2 */  
    53.        __le16  i_extra_isize;  
    54.        __le16  i_pad1;  
    55.        __le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */  
    56.        __le32  i_mtime_extra;  /* extra Modification time(nsec << 2 |epoch) */  
    57.        __le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */  
    58.        __le32  i_crtime;       /* File Creation time */  
    59.        __le32  i_crtime_extra; /* extraFileCreationtime (nsec << 2 | epoch) */  
    60.        __le32  i_version_hi;   /* high 32 bits for 64-bit version */  
    61. };  

    Dir

    用于保存所有目录的信息。

    根目录总是在inode表的第二项,而其子目录则在根目录文件的内容中定义。

    结构体如下:


    1. struct ext4_dir_entry {  
    2.        __le32  inode;                  /* Inode number文件入口的inode号,0表示该项未使用*/  
    3.        __le16  rec_len;                /* Directory entry length目录项长度*/  
    4.        __le16  name_len;               /* Name length文件名包含的字符数*/  
    5.        char    name[EXT4_NAME_LEN];    /* File name文件名*/  
    6. }; 

    关键词汇

    先回顾几个基本的概念,如果不是特别清楚下面几个概念的话,可以去google一下。

    inode:索引节点

    superblock:超级块

    block:文件系统块

    block group:文件系统块组

    disk block:磁盘块(512字节)

    block device:块设备

    VFS:虚拟文件系统

    EXT4存储结构

    假如把整个超级块比如一本书,那么文件系统的工作就是把要记录的内容,按页码,行段记录在这本书里。这当然也包括书的目录了。我们使用dumpe2fs工具输出:

    root@ubuntu:/home/user1# dumpe2fs -h s.img.ext4
    dumpe2fs 1.42.9 (4-Feb-2014)
    Filesystem volume name:   <none>
    Last mounted on:          <not available>
    Filesystem UUID:          57f8f4bc-abf4-655f-bf67-946fc0f9f25b
    Filesystem magic number:  0xEF53
    Filesystem revision #:    1 (dynamic)
    Filesystem features:      has_journal resize_inode filetype needs_recovery extent sparse_super large_file uninit_bg
    Default mount options:    (none)
    Filesystem state:         clean
    Errors behavior:          Remount read-only
    Filesystem OS type:       Linux
    Inode count:              46080
    Block count:              184320
    Reserved block count:     0
    Free blocks:              3382
    Free inodes:              44404
    First block:              0
    Block size:               4096
    Fragment size:            4096
    Reserved GDT blocks:      47
    Blocks per group:         32768
    Fragments per group:      32768
    Inodes per group:         7680
    Inode blocks per group:   480
    Last mount time:          Tue Jul 19 07:59:31 2016
    Last write time:          Tue Jul 19 07:59:31 2016
    Mount count:              2
    Maximum mount count:      -1
    Last checked:             Wed Dec 31 16:00:00 1969
    Check interval:           0 (<none>)
    Reserved blocks uid:      0 (user root)
    Reserved blocks gid:      0 (group root)
    First inode:              11
    Inode size:	          256
    Required extra isize:     28
    Desired extra isize:      28
    Journal inode:            8
    Default directory hash:   tea
    Journal backup:           inode blocks
    Journal features:         (none)
    Journal size:             11M
    Journal length:           2880
    Journal sequence:         0x00000004
    Journal start:            0
    



    Reserved GDT blocks:      609

    Blocks per group:         32768

    Fragments per group:      32768

    Inodes per group:         8128

    Inode blocks per group:   508

    Flex block group size:    16

    Filesystem created:       Mon May 14 13:30:51 2012

    Last mount time:          Sun Jan  6 18:51:16 2013

    Last write time:          Sun Jan  6 18:51:16 2013

    Mount count:              282

    Maximum mount count:      -1

    Last checked:             Mon May 14 13:30:51 2012

    Check interval:           0 (<none>)

    Lifetime writes:          20 GB

    Reserved blocks uid:      0 (user root)

    Reserved blocks gid:      0 (group root)

    First inode:              11

    Inode size:               256

    Required extra isize:     28

    Desired extra isize:      28

    Journal inode:            8

     

    首先,映入眼帘的是该超级块的相关重要参数,比如inode大小,块组含块数,块组inode数目等等。这些数据是存在ext4_super_blockext4_sb_info这两个结构体中,定义在ext4.h头文件里,它们不是本篇重要讨论的内容。我们只需要知道它们是存放一些超级块信息的结构体即可。

    接下来,可以看到ext4硬盘上的存储结构:

    Group 0: (Blocks 0-32767) [ITABLE_ZEROED]

      Checksum 0x7cf3, unused inodes 0

      Primary superblock at 0, Group descriptors at 1-2

      Reserved GDT blocks at 3-611

      Block bitmap at 612 (+612), Inode bitmap at 628 (+628)

      Inode table at 644-1151 (+644)

      2720 free blocks, 0 free inodes, 1383 directories

      Free blocks: 8888-8959, 9068, 9071-9135, 9144-9175, 9200-9207, 9213-9214, 9279, 9700-10120, 11823-11964, 12213-12870, 12879-13043, 13139-13254, 18432-19021, 22748-22975, 32549-32767

      Free inodes:

     

    这是块组0的情况,它表明块组0由块号为0-3276732768个块组成,超级块基本信息存在块0,块组描述符在块1-2,预留的块组描述符表在块3-611,块位图在块612中,inode位图在块628中,Inode表在块644-1151中,空闲的块有很多,空闲的inode没了。

    接下来,我们将重点分析这句废话中每个词的含义

            超级块基本信息:

                      我们在前面已经讲过了。顾名思义,不多解释。

             块组描述符

                      在内核中就是结构体ext4_group_desc,它包括的内容为:块位图块号,inode位图块号,inode表块号,空闲块计数,自由块计数等等。

             预留的块组描述符表

                      为以后要使用所留下来的空间。

             块位图

                      这个就是一个块使用情况记录表。记录哪些块使用,哪些块未使用。它的原理就是对整个块组中0-32767这总共32768个块中作一个映射。根据一个bytes8个位00000000,一个块有4096bytes也就是有4096*8=32768个位,这32768个位刚好对应了块组中32768的块。如果第N个块被使用了则标记第N位为1,否则为0

             inode位图

                      和上面的块位图一样,这个是inode的使用情况记录表。由超级块基本信息可以看到每个块组有8128inode,这里对inode的映射原理和块位图也是一样,只不过         没有用满一个块。

             inode

                      inode表就是具体存放inode信息的地方。在ext4中,inode的大小为256字节(ext2/3中仅有它的一半,128字节),一个块可以存放16inode,由于一个块组有8128          inode,总共需要8128/16=508个块存放inode表。这个值可以在超级块基本信息中的Inode blocks per group中看到。

    讲完了这些词的含义,我们对group 0有了初步的了解。那么group 1呢?

    Group 1: (Blocks 32768-65535) [ITABLE_ZEROED]

      Checksum 0xbb99, unused inodes 0

      Backup superblock at 32768, Group descriptors at 32769-32770

      Reserved GDT blocks at 32771-33379

      Block bitmap at 613 (+4294935141), Inode bitmap at 629 (+4294935157)

      Inode table at 1152-1659 (+4294935680)

      598 free blocks, 0 free inodes, 648 directories

      Free blocks: 33424-33439, 33442-33443, 33564-33627, 33644-33647, 33652-33663, 33725-33871, 33878-33931, 33934-33973, 33976-33983, 34046-34047, 34176-34303, 36008, 36015, 36019, 36412, 40299-40415

      Free inodes:

     

    我们看到group 1 中,primary superblock 变为了backup superblock,由于超级块基本信息对于文件系统至关重要,为了系统的健壮性,ext文件系统在每个块组中都进行了备份。ext4考虑到在每个块组中都备份有点多余,尤其是组描述符表所以就仅在块号以357为幂的块组上进行备份。

    用个表格表示超级块中块组的结构:

    ext4 超级块

    块组描述符

    Reserved GDT Blocks

    数据块位图

    Inode位图

    inode 表

    数据块

    1 block

    若干blocks

    若干 blocks

    1 block

    1 block

    若干

    好多好多块

                                                                                                                                                        

    inode

    Purpose

    0

    Doesn't exist; there is no inode 0.

    1

    List of defective blocks.

    2

    Root directory.

    3

    ACL index.

    4

    ACL data.

    5

    Boot loader.

    6

    Undelete directory.

    7

    Reserved group descriptors inode.

    8

    Journal inode.

    11

    First non-reserved inode. Usually this is the lost+found directory.

     

    块寻址

    ext4的块寻址已经改为48位。这种设计改动是为了支持更大的文件系统大小。EXT4使用了区段(extents)这个概念,取代了过去早期UNIX文件系统中(ext2/3)中低效的非直接块映射机制。区段和NTFS上的cluster有点类似,它们都是选定了一个特定的块地址并把数个块组合一个区间。一个文件如果是碎片化的,那么就意味它着拥有多个区段,ext4会尽它自己的努力保持文件连续。

     

    这种新的块寻址策略导致了先前工具的大部分问题。举个列子:

     

    [root@localhost Desktop]# stat math.c

      File: `math.c'

      Size: 1477               Blocks: 8          IO Block: 4096   regular file

    Device: fd00h/64768d     Inode:420402      Links: 1

    Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)

    Access: 2013-01-05 15:07:11.815541582 +0800

    Modify: 2012-08-20 13:40:02.496797954 +0800

    Change: 2012-12-30 11:28:54.751357610 +0800

     

     

    由上面得到文件math.cInode号为420402

    [root@localhost Desktop]# istat /dev/mapper/VolGroup-lv_root 420402

    inode: 420402

    Allocated

    Group: 51

    Generation Id: 1062005310

    uid / gid: 0 / 0

    mode: rrw-r--r--

    Flags:

    size: 1477

    num of links: 1

     

    Inode Times:

    Accessed:         2013-01-05 15:07:11 (CST)

    File Modified:   2012-08-20 13:40:02 (CST)

    Inode Modified:        2012-12-30 11:28:54 (CST)

     

    Direct Blocks:

    127754

     

     

    由上面的命令结果可以看到,Inode位于节点上块组51上,留意上面命令最下面有Direct Blocks这一行,这一行写着127754。在ext4的文件系统中,由于direct block映射的块寻址机制被取代,而采取的是extent区段树的块寻址。这个地方的值基本上是无效的。127754这个值十六进制表示为0x1f30a,我们在稍后的讨论这个值的来源。

    我们知道了math.c这个文件的inode号码为420402,那么怎样知道它数据块是拿一个呢?

    由前面的内容我们知道,每个块可以存16inode,那么420402则在第420402/16=26275.125个块中,也就是位于第26275个块的第二个位置。每个块组有508inode块,那么26725/508=51.72可以得知,位于块组51号之中,这个值可以在我们之前istat中可以验证。

    那么具体是51块组中的哪个块呢?我们先确定这个inode块是在块组中的第几个块。因为每个块组有508inode块,51块组前面共有51*508=25908个块。第26275inode块在51块组中排在26275-25908=367的位置。查看51块组的描述:

     

    Group 51: (Blocks 1671168-1703935) [ITABLE_ZEROED]

      Checksum 0x5ffd, unused inodes 0

      Block bitmap at 1572867 (+4294868995), Inode bitmap at 1572883 (+4294869011)

      Inode table at 1574420-1574927 (+4294870548)

      34 free blocks, 1 free inodes, 541 directories

      Free blocks: 1672899, 1673339, 1673344, 1674035, 1674054, 1674062, 1674077, 16

    74334, 1674353-1674354, 1674423, 1675259, 1675754-1675755, 1675763, 1675860-1675

    861, 1675867, 1675979, 1676183, 1676287, 1676367, 1676507, 1676526-1676527, 1676

    567, 1676711, 1676743, 1676924-1676925, 1676934, 1691649, 1691658, 1691707

      Free inodes: 422608

     

    看到inode的起点位于1574420,由此,我们想要找的inode信息的块就存在于1574787inode块中的第二个。

    可以使用blkcat查看1574787的内容,我们用vi切换到16进制模式打开如下:

     

    0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000080: 1c00 0000 4430 c1a7 c8f1 733d fc8a 6cb1  ....D0....s=..l.

    0000090: 58a8 b04f 04a0 6538 0000 0000 0000 02ea  X..O..e8........

    00000a0: 0706 3c00 0000 0000 2200 0000 0000 0000  ..<.....".......

    00000b0: 7365 6c69 6e75 7800 0000 0000 0000 0000  selinux.........

    00000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    00000d0: 0000 0000 0000 0000 0000 0000 7379 7374  ............syst

    00000e0: 656d 5f75 3a6f 626a 6563 745f 723a 6164  em_u:object_r:ad

    00000f0: 6d69 6e5f 686f 6d65 5f74 3a73 3000 0000  min_home_t:s0...

    0000100: a481 0000 c505 0000 1fd1 e750 f6b4 df50  ...........P...P

    0000110: b2cd 3150 0000 0000 0000 0100 0800 0000  ..1P............

    0000120: 0000 0800 0100 0000 0af3 0100 0400 0000  ................

    0000130: 0000 0000 0000 0000 0100 0000 d64a 1c00  .............J..

    0000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................

     

     我们知道inodesize大小为256字节,那么第二个inode的起始位置也就是256=0x100处。

    这个时候,我们看下inode的数据结构:

     

    位置

    名称

    描述

    0x0

    __le16

    i_mode

    文件模式

    0x2

    __le16

    i_uid

    所有者UID.

    0x4

    __le32

    i_size_lo

    文件大小.

    0x8

    __le32

    i_atime

    读取时间.

    0xC

    __le32

    i_ctime

    Inode修改时间

    0x10

    __le32

    i_mtime

    文件修改时间.

    0x14

    __le32

    i_dtime

    删除时间

    0x18

    __le16

    i_gid

    GID.

    0x1A

    __le16

    i_links_count

    硬链接计数.

    0x1C

    __le32

    i_blocks_lo

    块计数(512字节)

    0x20

    __le32

    i_flags

    文件标识(ext4使用extent需要标记0x80000)

    ...

    0x28

    __le32

    i_block[EXT4_N_BLOCKS=15]

    块映射(ext2/3)或区段树(ext4)

    ...

     

    我们按照表中的结构,对照上面的块码:

     

    偏移

    大小

    名称

    描述

    0x0

    0x81a4

    i_mode

    文件模式

    0x2

    0x0000

    i_uid

    所有者UID.

    0x4

    0x0000 05c5

    i_size_lo

    文件大小.

    0x8

    0x50e7 d11f

    i_atime

    读取时间.

    0xC

    0x50df b4f6

    i_ctime

    Inode修改时间

    0x10

    0x5031 b2cd

    i_mtime

    文件修改时间.

    0x14

    0x0000 0000

    i_dtime

    删除时间

    0x18

    0x0000

    i_gid

    GID.

    0x1A

    0x0001

    i_links_count

    硬链接计数.

    0x1C

    0x0000 0008

    i_blocks_lo

    块计数(512字节)

    0x20

    0x0080 0000

    i_flags

    文件标识(ext4使用extent需要标记0x80000)

    ...

    0x28

     ...

    i_block[EXT4_N_BLOCKS=15]

    块映射(ext2/3)或区段树(ext4)

    ...

     

    细心的同学会发现大小的顺序是倒过来的,这是因为__lexx类型,lelittle endian小端开始的缩写,意思就是从小到大的顺序。我们看到文件的大小为0x5c5=1477,这说明我们找的正是math.cinode

     

    因为ext4 使用区段去代替了块映射去查找文件的内容。从40-9960个字节过去是用作块映射的,如今用作存储extent信息。extent结构体有12字节的大小,反应快的同学马上会说,那么一个inode可以存放最多5extent。然而这是不对的,因为前12个字节(40-51)被段头(extent header)所占据,所以,一个inode中的区段数最多只能是4

     

    现在,我们重点开始讲区段树(extent tree)

    ext4中,区段树取代了旧式的逻辑块映射。这是因为在老的模式中,分配连续的1000个块需要映射这1000个块的地址。但使用了区段,只需要映射一个区段并把区段的长度标记为1000ee_len=1000)。如果起用了flex_bg的功能,一个区段可以分配一个很大的文件,这降低了元数据的大小,也提高了硬盘的效率。inode必须使用区段标记0x80000开启区段的功能。

    区段的结构是树形的。每个树节点的起始为:struct ext4_extent_header(这是一个结构体,我们接下来会给大家描述它的内容)。如果一个节点是树的内部节点(即eh.eh_depth>0),那么eh.eh_entries的指针将指向struct ext4_extent_idx;每个这些索引都指向一个块,块中包含更多的区段树中的节点。如果节点是树的叶子节点(eh.eh_depth=0),那么eh.eh_entries的指针将指向struct ext4_extent;这些结构体中指向文件的数据块。区段树的根节点存在inode.i_block,也就是我们在前面讨论的从40-99的那60个字节里。

     

    说了这么多,我们还是赶紧看看extent的结构吧;

     

    首先出场的是段头(extent header)

     

    偏移

    大小

    名称

    描述

    0x0

    __le16

    eh_magic

    幻数magic number, 0xF30A.

    0x2

    __le16

    eh_entries

    区段数.

    0x4

    __le16

    eh_max

    最大的区段数.

    0x6

    __le16

    eh_depth

    段节点在段树中的深度。0则表示为叶子节点,指向数据块;否则指向其它段节点。

    0x8

    __le32

    eh_generation

    暂不讨论

     

    同样的,对照我们的实际数据看看

     

    偏移

    大小

    名称

    描述

    0x0

    0xf30a

    eh_magic

    幻数magic number, 0xF30A.

    0x2

    0x0001

    eh_entries

    区段数.

    0x4

    0x0004

    eh_max

    最大的区段数.

    0x6

    0x0000

    eh_depth

    段节点在段树中的深度。0则表示为叶子节点,指向数据块;否则指向其它段节点。

    0x8

    0x0000 0000

    eh_generation

    暂不讨论

     

     

    接下来我们先看struct ext4_extent_idx,这个结构在前面我们有提到过,用于extent树的内部节点。

     

    偏移

    大小

    名称

    描述

    0x0

    __le32

    ei_block

    逻辑块号.

    0x4

    __le32

    ei_leaf_lo

    区段树中下一层的区段节点块地址(低32位),可以指向叶子节点或者内部节点。

    0x8

    __le16

    ei_leaf_hi

    上一栏的高16位地址

    0xA

    __u16

    ei_unused

    未使用

     

    我们接着看struct ext4_extent,叶子节点的结构体

     

    偏移

    大小

    名称

    描述

    0x0

    __le32

    ee_block

    此区段的第一个块号,起始块号

    0x4

    __le16

    ee_len

    区段内包含的块数.

    0x6

    __le16

    ee_start_hi

    此区段所指向的块号(高16位)

    0x8

    __le32

    ee_start_lo

    此区段所指向的块号(低32位)

     

    对照我们的实际数据看看

     

    偏移

    大小

    名称

    描述

    0x0

    0x0000 0000

    ee_block

    此区段的第一个块号,起始块号

    0x4

    0x0001

    ee_len

    区段内包含的块数.

    0x6

    0x0000

    ee_start_hi

    此区段所指向的块号(高16位)

    0x8

    0x001c 4ad6

    ee_start_lo

    此区段所指向的块号(低32位)

     

    由上表可以看到,因为我们的文件较小,这里作为叶子节点直接指向了文件数据块。数据块号为0x001c4ad6=1854166。我们使用命令查看块中的内容:

    [root@localhost Desktop]# blkcat /dev/mapper/VolGroup-lv_root 1854166

    #include <stdlib.h>

    #include <math.h>

    ...

     

    呵呵,可以看到,这就是我们的math.c文件。

     

    思考:

    请读者找一个大于4k的文件,看看能不能找到它的数据块。

     

    删除文件

    执行rm后删除文件,数据块并没有被清除,inode被释放,有下面3项会改变: 1. 文件大小被置为0

        2. 段头中的区段值被设为0

        3. 区段被清空

    清空了区段意味着我们会失去文件起始物理块的地址和区段的长度。也就是说,在inode中已经不存在元数据可以帮我们恢复文件。这种行为和ext3回收inode时清除inode中的块指针很相似。这样就意味着我们只能靠传统的file-carving去恢复文件。

    还记得在上一章中,我们提到过的结构体struct ext4_extent_idx。这个结构体表示在extent tree中的节点。 我们在前面的章节已经阐述过,ext4使用extent取代了传统的block映射方式。我们的案例中只展示了只有一个extent的情况。本篇文章将介绍多个extent情况下的具体细节。

     

    在本文中,我们选取了文件/var/log/messages,它是系统日志的记录文件,由于它的角色特殊,时间长了会造成给很多的碎片。我们还是先看看他的inode,方法和(一)中描述的一致,在此不重复了。

     

     

    0000c00: 8081 0000 d036 0000 814b ee50 7f4b ee50  .....6...K.P.K.P

    0000c10: 7f4b ee50 0000 0000 0000 0100 2000 0000  .K.P........ ...

    0000c20: 0000 0800 0100 00000af30400 0400 0000  ................

    0000c30: 0000 0000 0000 0000 0100 0000 58c2 0b00  ............X...

    0000c40: 0100 0000 0100 0000 e599 1b00 0200 0000  ................

    0000c50: 0100 0000 41e6 2f00 0300 0000 0100 0000  ....A./.........

    0000c60: b878 1c00 275f ea72 0000 0000 0000 0000  .x..'_.r........

    0000c70: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000c80: 1c00 0000 c018 94d1 c018 94d1 c0e5 ea86  ................

    0000c90: 9bea e850 d0a4 fcb4 0000 0000 0000 02ea  ...P............

    0000ca0: 0706 4000 0000 0000 1f00 0000 0000 0000  ..@.............

    0000cb0: 7365 6c69 6e75 7800 0000 0000 0000 0000  selinux.........

    0000cc0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000cd0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000ce0: 7379 7374 656d 5f75 3a6f 626a 6563 745f  system_u:object_

    0000cf0: 723a 7661 725f 6c6f 675f 743a 7330 0000  r:var_log_t:s0..

     

     

    0x0af3开始,这是extent header起始的标记,我们还是像(一)那样,对照着表看

     

    偏移

    大小

    名称

    描述

    0x0

    0xf30a

    eh_magic

    幻数magic number, 0xF30A.

    0x2

    0x0004

    eh_entries

    区段数.

    0x4

    0x0004

    eh_max

    最大的区段数.

    0x6

    0x0000

    eh_depth

    段节点在段数中的深度。0则表示为叶子节点,指向数据块;否则指向其它段节点。

    0x8

    0x0000

    eh_generation

    暂不讨论

     

    因为这里看到depth0,说明extent中指向的是数据块。在extent header中接下来的将extent是我们把接下来的数据对应到它的表中

     

    偏移

    大小

    名称

    描述

    0x0

    0x0000 0000

    ee_block

    此区段的第一个块号,起始块号

    0x4

    0x0001

    ee_len

    区段内包含的块数.

    0x6

    0x0000

    ee_start_hi

    此区段所指向的块号(高16位)

    0x8

    0x000b c258

    ee_start_lo

    此区段所指向的块号(低32位)

     

    接下来的12个字节

     

    偏移

    大小

    名称

    描述

    0x0

    0x0000 0001

    ee_block

    此区段的第一个块号,起始块号

    0x4

    0x0001

    ee_len

    区段内包含的块数.

    0x6

    0x0000

    ee_start_hi

    此区段所指向的块号(高16位)

    0x8

    0x001b 99e5

    ee_start_lo

    此区段所指向的块号(低32位)

     

    再接下来的12个字节

     

    偏移

    大小

    名称

    描述

    0x0

    0x0000 0002

    ee_block

    此区段的第一个块号,起始块号

    0x4

    0x0001

    ee_len

    区段内包含的块数.

    0x6

    0x0000

    ee_start_hi

    此区段所指向的块号(高16位)

    0x8

    0x00f2 e641

    ee_start_lo

    此区段所指向的块号(低32位)

     

    最后的12个字节 

    偏移

    大小

    名称

    描述

    0x0

    0x0000 0003

    ee_block

    此区段的第一个块号,起始块号

    0x4

    0x0001

    ee_len

    区段内包含的块数.

    0x6

    0x0000

    ee_start_hi

    此区段所指向的块号(高16位)

    0x8

    0x001c 78b8

    ee_start_lo

    此区段所指向的块号(低32位)

     

    可以通过使用blkcat看到4个块刚好凑成了messages文件,疑心重的同学可以把4个块拼成一个文件,用md5sum比较一下。这里我们并没有想看到extent中的内部节点情况。没关系,我们系统日志文件时会随着时间增长。正在笔者撰写此文时,messages已经变大了,并且超过了16k的大小,也就是超出了4个块。这时候我们看看messagesinode信息,方法不重复了。

     

    0000c00: 8081 0000 4f51 0000 eb84 ef50 ea84 ef50  ....OQ.....P...P

    0000c10: ea84 ef50 0000 0000 0000 0100 3800 0000  ...P........8...

    0000c20: 0000 0800 0100 00000af3 0100 0400 0100  ................

    0000c30: 0000 0000 0000 0000 7c03 1c00 0000 0b00  ........|.......

    0000c40: 0100 0000 0100 0000 e599 1b00 0200 0000  ................

    0000c50: 0100 0000 41e6 2f00 0300 0000 0100 0000  ....A./.........

    0000c60: b878 1c00 275f ea72 0000 0000 0000 0000  .x..'_.r........

    0000c70: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000c80: 1c00 0000 c80e c097 c80e c097 accd 3948  ..............9H

    0000c90: 9bea e850 d0a4 fcb4 0000 0000 0000 02ea  ...P............

    0000ca0: 0706 4000 0000 0000 1f00 0000 0000 0000  ..@.............

    0000cb0: 7365 6c69 6e75 7800 0000 0000 0000 0000  selinux.........

    0000cc0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000cd0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

    0000ce0: 7379 7374 656d 5f75 3a6f 626a 6563 745f  system_u:object_

    0000cf0: 723a 7661 725f 6c6f 675f 743a 7330 0000  r:var_log_t:s0..

     

     

    经过一段时间的练习,同学们应该不需要对照表来识辨这些16进制码的含义了,如果不熟练的话,可以回过头多看几遍。我们看到这个inode较之前有了变化。extent的区段数变成了1,区段树的深度变成了1。区段树深度为1,这说明非叶子节点。

     

    偏移

    大小

    名称

    描述

    0x0

    0x0000 0000

    ei_block

    逻辑块号.

    0x4

    0x001c 037c

    ei_leaf_lo

    区段树中下一层的区段节点块地址(低32位),可以指向叶子节点或者内部节点。

    0x8

    0x0000

    ei_leaf_hi

    上一栏的高16位地址

    0xA

    0x000b

    ei_unused

    未使用

     

    使用blkcat查看文件系统块1835900的内容,

     

    0000000: 0af3 0e00 5401 0000 0000 0000 0000 0000  ....T...........

    0000010: 0100 0000 58c2 0b00 0100 0000 0100 0000  ....X...........

    0000020: e599 1b00 0200 0000 0100 0000 41e6 2f00  ............A./.

    0000030: 0300 0000 0100 0000 b878 1c00 0400 0000  .........x......

    0000040: 0100 0000 2d8b 1b00 0500 0000 0100 0000  ....-...........

    0000050: 9a79 1c00 0600 0000 0100 0000 0d82 1b00  .y..............

    0000060: 0700 0000 0100 0000 1182 1b00 0800 0000  ................

    0000070: 0100 0000 1382 1b00 0900 0000 0100 0000  ................

    0000080: 1682 1b00 0a00 0000 0100 0000 1882 1b00  ................

    0000090: 0b00 0000 0300 0000 034e 1c00 0e00 0000  .........N......

    00000a0: 0200 0000 074e 1c00 1000 0000 0400 0000  .....N..........

    00000b0: e082 0c00 0000 0000 0000 0000 0000 0000  ................

     

     

    从上面的数据,我们可以看到有0x000e个区段,也就是在extent header后有14extent或者extent ixd的结构体。接着看到extent最大数为0x0154=340,这个数字是怎么来的呢?我们知道在一个inode里面,这个值是4,那是因为('extent space' - 'extent header size') / 'extent size'  (60-12)/12=4,那么在这里也一样,只不过60这里要变为4096,因为我们不在inode中,而是在一个块中,即4096-12=4084,4084/12340.333,最后还剩4个字节浪费了。再接着,是树的深度,也就是0x0000表明是叶子节点。那么我们知道,这个文件由着14block的块组成。有兴趣的同学可以自己把文件dump出来拼一下。呵呵。


    simg2img system.img s.new
    
    mount  s.new /mnt/data
    
    修改launcher2.apk
    
    make_ext4fs -l 891M -s s.s /mnt/data

    void CSortlogcatDlg::OnButton2() 
    {
    	// TODO: Add your control notification handler code here
    	CString strText;
    	CString szLine; //存储行字符串
    	
    	CStdioFile file;
    	CString filepath;
    	GetDlgItemText(IDC_EDIT1,filepath);
    	file.Open(filepath,CFile::modeRead);//打开文件
    	
    	//逐行读取字符串
    	int linescount=0;
    	int linestot=0;
    
    	typedef CArray <int,int&> array;  //   定义二维动态数组  
    	array num;
    
    	num.SetSize(1000);
    	int tot=0;
    	
    	while( file.ReadString( szLine ) )
    	{
    	    char* p = strstr(szLine,".xml:");
    		if(p==0)continue;
    		p += strlen(".xml:");
    		char* pafter = strchr(p,':');
    		if(pafter){
    			pafter[0]=0;
    			//m_list.AddString(p);			
    			int d = atoi(p);
    			num[tot]=d;
    			tot++;
    		}		
    	}
    	
    	//关闭文件
    	file.Close();
    	int i;
    	int j;
    	int temp;
    	for(i=0;i<tot-1;i++){
    		for(j=i+1;j<tot;j++){
    			if(num[j]<num[i]){
    				temp=num[j];
    				num[j]=num[i];
    				num[i]=temp;
    			}
    		}
    	}
    	CString cs;
    	for(i=0;i<tot;i++){
    		cs.Format("%d",num[i]);
    		m_list.AddString(cs);
    		if(num[i+1]!=num[i]+1){
    			m_list.AddString("==========================");
    		}
    	}
    }



    展开全文
  • D-Recovery For Linux是在windows平台下安装使用,对EXT2/EXT3/EXT4文件系统的分区进行读取并进行数据恢复,具备如下功能:1、 扫描并恢复丢失的EXT2/EXT3/EXT4文件系统分区,也就是分区表恢复。2、 EXT2/EXT3/EXT4...
  • 可以打开镜像文件及硬盘设备文件查看具体的 文件系统结构信息,如超级块,块组信息,文件inode,目录信息,文件信息,提取文件内容等。本人写这个程序就是 为了学习一下ext2/3,也希望通过本程序能让读者了解ext2/3...
  • XP 下如何查看linux : 如果你有一个Windows/Linux双重启动的系统,你可能会知道这个问题:你可以在Linux里访问...本指南展示了三种从Windows里访问Linux分区(ext2或ext3文件系统)的方法:Explore2fs,
  • 目录 编译准备 搭建编译环境 CentOs安装 内核源代码下载 内核模块选择/安装 附录 编译准备 1.搭建编译环境 sudo yum install gcc ...2)打开VMware虚拟机安装镜像。 3.内核源代码下载 下载代码 下载Linux-3.50.ta...
  • Linux杂项(001) - ext4magic文件恢复

    千次阅读 2018-11-19 15:59:57
    ext4 文件系统。就想到了一个软件,ext4magic 那么就安装吧。百度一波。编译的时候 configure: error: You must install the develop packages "ext2fs , blkid , e2p , uuid" to build ext4ma...
  • 制作imx6ull Linux系统的img镜像 参考链接:https://blog.csdn.net/qingtian11112/article/details/99825257 相信玩过树莓派或者香橙派的人都知道,我们利用SD卡启动Linux系统的时候,是将官网提供的img镜像通过Win32...
  • Btrfs 简介 文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3,ext 文件系统以其卓越的稳定性成为了事实上的 Linux 标准文件系统。近年来 ext2/3 暴露出了一些扩展性问题,于是便催生...
  • mac os 如何读取 Linux ext4 格式的硬盘很多时候需要在macOS上操作Linuxext4分区,然后macOS系统默认并不支持ext4等分区格式。而MacOS并不支持读取这个格式的文件,因此需要借助其他的软件来实现读取正解是装个 ...
  • Linux各个发行版镜像下载

    千次阅读 2011-05-19 16:11:00
    Linux各个发行版镜像下载(不断更新) Linux国外的镜像服务器比较多,国内校园网内有不少大学也有Linux镜像服务器,但是在公网下载比较慢,有的还需要用户名密码才能下载 摘一段“Linux一句话问答”...
  • EXT3文件系统与LINUX多年的相随相伴,使EXT3成为一个相当稳定成熟的文件系统,在EXT4文件系统稳定之前,EXT3已成为绝大数LINUX发行版默认的文件系统。EXT3文件系统以其的稳定性、兼容性、扩展性为LINUX征战服务器...
  • 一、制作Linux LiveCD 安装到U盘 1. 1. 下载Cent OS 的liveCd的iso光盘镜像,使用虚拟机安装,或者使用DVD光盘刻出来(我使用的是虚拟机,更加方便,注意下载的版本如果低于6.5可能会造成不能安装到硬盘,我选择用的...
  • Linux各个发行版镜像下载(不断更新)Linux国外的镜像服务器比较多,国内校园网内有不少大学也有Linux镜像服务器,但是在公网下载比较慢,有的还需要用户名密码才能下载摘一段“Linux一句话问答”给各位看看0001 不...
  • 在使用开发板开发时,时常需要把编译好的镜像文件烧写至开发板,通常我们使用OTG在线烧写方式,开发阶段调试效率很高,也可以使用TF卡烧录,就需要先把TF卡做成类似启动盘,像Windows用U盘做操作系统时,要有一个...
  • Linux储存管理2 文件系统(ext4、xfs),文件链接,raid 一、 文件系统系统详解 1.EXT4和XFS的简介 EXT4是第四代扩展文件系统,是Linux系统下的日志文件系统,是ext3文件系统的后继升级版本。 XFS一种高性能的日志...
  • ISO/Ghost 镜像文件概念(裸机安装,无光驱安装,跨平台安装) ISO是镜像文件:所谓镜像文件其实和ZIP压缩包类似,它将特定的一系列文件按照一定的格式制作成单一的文件,以方便用户下载和使用,例如一个测试版的...
  • 首先应该知道,SLES11 sp1的内核(2.6.32)是支持ext4文件系统的,但是这个发行版默认使用ext3文件系统,对ext4的支持并不成熟,并不鼓励用户使用ext4文件系统,所以默认安装的时候没有安装ext4的模块,需要手动安装...
  • ext4解包和重新打包

    千次阅读 2020-04-02 14:06:11
    有的官方包用的是.img.ext4格式,要用Linux解包 以下用Ubuntu做例子讲解打包解包方法 也可以用相同的原理修改EXT4文件系统的.img 1.需要: Ubuntu操作系统http://www.ubuntu.org.cn/download/desktop 解打包工具 ...
  • 系统环境:龙芯1B开发板(mips32指令集)、Linux3.0.0内核 编译环境:ubuntu10.04 ,gcc-3.4.6-2f   1.mkcramfs工具 打开地址:http://sourceforge.net/projects/cramfs/,下载cramfs-1.1.tar.gz #tar zxf cramfs-1.1...
  • Clonezilla和Tuxboot简介 Clonezilla 是一个很好的系统克隆工具,它可以说是吸取了 Norton Ghost 和 Partition Image 的优点。即不仅支持对整个系统进行...Clonezilla是一个用于Linux,Free-Net-OpenBSD,Mac OS X,...
  • linux下文件和目录的颜色代表的含义 http://jayjayjays.iteye.com/blog/306787蓝色 表示目录;绿色表示可执行文件; 红色 表示压缩文件; 浅蓝 色表示链接文件; 灰色 表示其它文件; 红色闪烁 表示链接的文件...
  • # PHP官方镜像 FROM php:7.2-fpm # yaf 扩展 RUN pecl install yaf-3.2.2 && docker-php-ext-enable yaf # redis 扩展 RUN pecl install redis-5.2.2 && docker-php-ext-enable redis # mong

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,922
精华内容 6,768
关键字:

linux打开ext4镜像

linux 订阅