Android中我们经常会使用android.os.StatFs来获取关于文件系统空间的状态信息。

File sdcardDir = Environment.getExternalStorageDirectory(); StatFs sf = new StatFs(sdcardDir.getPath()); long blockSize = sf.getBlockSize(); long blockCount = sf.getBlockCountLong(); long availCount = sf.getAvailableBlocksLong(); Log.d("", "block大小:"+ blockSize+",block数目:"+ blockCount+",总大小:"+blockSize*blockCount/1024+"KB"); Log.d("", "可用的block数目::"+ availCount+",剩余空间:"+ availCount*blockSize/1024+"KB"); 

但上面的方法我们会发现剩余空间和df命令显示的Free大小不一样,这是怎么回事呢?
看看df的代码(system/core/toolbox/df.c)

39        printf("%-20s ", s);40        printsize((long long)st.f_blocks * (long long)st.f_bsize);41        printf(" ");42        printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize);43        printf(" ");44        printsize((long long)st.f_bfree * (long long)st.f_bsize);45        printf(" %d\n", (int) st.f_bsize);

发现df使用的是f_bfree,查看下statfs的定义

/** file system statistics*/struct statfs {int f_version; /* version/type of statfs, 0 for now*/int f_type; /* type of info, zero for now */ulong_t f_bsize; /* optimal file system block size */fsblkcnt_t f_blocks; /* total data blocks in file system */fsblkcnt_t f_bfree; /* free block in fs */fsblkcnt_t f_bavail; /* free blocks avail to non-superuser*/fsfilcnt_t f_files; /* total file nodes in file system */fsfilcnt_t f_ffree; /* free file nodes in fs */#if !defined(_KERNEL) && defined(__64BIT__)fsid64_t f_fsid; /* file system id */#elsefsid_t f_fsid; /* file system id */#endifint f_vfstype; /* what type of vfs this is */ulong_t f_fsize; /* fundamental file system block size*/int f_vfsnumber; /* vfs indentifier number */int f_vfsoff; /* reserved, for vfs specific data offset */int f_vfslen; /* reserved, for len of vfs specific data */int f_vfsvers; /* reserved, for vers of vfs specific data */char f_fname[32]; /* file system name (usually mount pt.) */char f_fpack[32]; /* file system pack name */int f_name_max; /* maximum component name length for posix */};

可以看到

fsblkcnt_t f_bfree; /* free block in fs */fsblkcnt_t f_bavail; /* free blocks avail to non-superuser*/

查看SDK

public long getAvailableBlocksLong ()

The number of blocks that are free on the file system and available to applications. This corresponds to the Unix statvfs.f_bavail field.

也就是说getAvailableBlocksLong()返回的是f_bavail,这块是不包含超级用户的预留空间的。如果要得到和df一样的大小请使用getFreeBlocksLong()。

public long getFreeBlocksLong ()

The total number of blocks that are free on the file system, including reserved blocks (that are not available to normal applications). This corresponds to the Unix statvfs.f_bfree field. Most applications will want to use getAvailableBlocks() instead.

那什么是“超级用户预留空间”呢?请看ext4文件系统的说明 https://lwn.net/Articles/546473/:

Currently in ENOSPC condition when writing into unwritten space, or punching a hole, we might need to split the extent and grow extent tree. However since we can not allocate any new metadata blocks we’ll have to zero out unwritten part of extent or punched out part of extent, or in the worst case return ENOSPC even though use actually does not allocate any space.

Also in delalloc path we do reserve metadata and data blocks for the time we’re going to write out, however metadata block reservation is very tricky especially since we expect that logical connectivity implies physical connectivity, however that might not be the case and hence we might end up allocating more metadata blocks than previously reserved. So in future, metadata reservation checks should be removed since we can not assure that we do not under reserve.

And this is where reserved space comes into the picture. When mounting the file system we slice off a little bit of the file system space (2% or 4096 clusters, whichever is smaller) which can be then used for the cases mentioned above to prevent costly zeroout, or unexpected ENOSPC.

The number of reserved clusters can be set via sysfs, however it can never be bigger than number of free clusters in the file system.

更多相关文章

  1. Android中获取(RAM)总运存大小和可用运存大小
  2. QQ空间手机版的十件不为人知的事
  3. 【转】Android -- 探究Android的多分辨率支持以及各种类型图标尺
  4. android文件系统及其制作

随机推荐

  1. Can't dispatch DDM chunk 52454151: no
  2. android之ContentObserver内容观察者的使
  3. Android Selector Shape使用详解
  4. Android 获取系统相册中的所有图片
  5. Android 项目开发问题整理(持续更新)
  6. 【Android】解析Paint类中MaskFilter的使
  7. android 通话记录的查询与删除
  8. 转到编辑联系人的系统界面 编辑 添加
  9. android开发环境搭建和部署
  10. android apk 防止反编译技术第二篇-运行