下使用XFS格式mac支持的硬盘格式的吗

一次Linux下testdisk+gdisk恢复;硬盘之前状况,用gdisk进行硬盘分区(SATA;我已无法确定引起这次硬盘错误的原因,但我确实这么;原因一,从另一个硬盘的/home挂载点复制了大量;原因二,在这次准备复制数据的之前,我没有将硬盘固;1,硬盘错误引起分区无法读取,挂载,开始纳闷哪里;2,运行gdisk-l/dev/sdb,显示如下;有警告信息
一次Linux下testdisk+gdisk恢复XFS文件系统及数据的经历硬盘之前状况,用gdisk进行硬盘分区(SATA标准,3.6T容量),1.6T+2.0T两个分区,然后用mkfs.xfs格式化分区,最后结果就是,GPT分区表+两个XFS文件系统的硬盘(/dev/sdb,/dev/sdb1,/dev/sdb2)我已无法确定引起这次硬盘错误的原因,但我确实这么做过:原因一,从另一个硬盘的/home挂载点复制了大量数据到/dev/sdb1,然后我就将硬盘的数据线和电源线都拔掉了,这个动作在系统运行和关闭的两种情况下都做过,(SATA硬盘是否安全的支持热插拔?)原因二,在这次准备复制数据的之前,我没有将硬盘固定,也没有平放在台面(有一点斜度),然后开机,(胡乱的猜想着斜坡加载技术)下面进入正题:1,硬盘错误引起分区无法读取,挂载,开始纳闷哪里出了问题2,运行gdisk -l /dev/sdb,显示如下有警告信息及注意事项,虽然这里的标记GPT:damaged说明GPT有问题,但最后还是显示出了有分区的信息存在,(GPT分区表信息应该没有彻底损坏,不然怎么读取到两个分区的信息的呢),两个分区里Code标记都变成了0700(Microsoft basic data),正常的应该是8300(Linux filesystem),这个标记应该说明的是XFS文件系统的superblock信息毁了,这是后来经过XFS文件系统工具xfs_repair知道的详细分区情况,但是是得出来的结果有问题的gdisk检测到五个问题,(惊讶,这么多的问题)3,进行到这里,我着急了,于是寻求帮助首先,尝试了xfs_repair /dev/sdb,这个命令进行了几次,因为中途中断过,这个修复时间是比较长的,几小时(差不多3,4小时?)后得到的结果却是无法检测验证到有效的备份superblock信息,(失败,心都凉了)然后,找到testdisk工具,大略的看了下说明就上手做(英文实在是差,仔细地看也不明白),第一次进行Analyse后,完全不知道做什么,就直接退出然后就去测试查看,运行lsblk,gdisk,没有任何改变,(此刻是没抱什么希望的),输出的日志文件testdisk.log也完全看不懂,但我在日志文件里看到了有XFS这三个字母的身影,(此时心中还是有一丝喜悦的)4,继续网上搜索,寻求答案,(辛辛苦苦建立的文件数据啊,那个心情真是无奈啊)使用testdisk进行第二次Analyse(分析目前分区结构及搜寻丢失的分区),经过6小时的分析与搜索后,我大胆的进行了第二个动作,转换分区类型,(当时的想法是inode及data block里记录的信息应该是不会丢失或被覆盖的),于是我选择了Linux reserved(谷歌翻译了一下,“Linux保留”,这里是没有Linux filesystem的,找来找去也没找到更合适的了),再进入子菜单选择了XFS(还有XFS2,XFS3,XFS4,这里是比较疑惑的,网上没有找到任何答案),至此点击写入,然后退出。再一次阅读testdisk.log文件,(这里有点小插曲,我在主文件侠里找不到testdisk.log文件,进行whereis testdisk.log搜寻,这个文件怎么会跑到/usr/src/linux-3.10.3-1-ARCH/testdisk.log这里了呢)?5,testdisk.log文件内容如下:这里是系统的一些相关信息这里是选择了EFI GPT选项后得出的结果,在这里就分析出了当前的分区结构,只有一个Linux Reserved分区类型的分区,(这里的这个分析是不是肯定的)这里是应该是选择了Analyse选项后再点击quick search得到的,大概是两段内容,第一,对于分区1文件系统的标记搜索,成功,(这个标记是什么,superblock?,不是损毁了吗?)。第二,对于分区2文件系统的标记搜索,在这里搜索到了很多标记,但是在比对数据(能这样表达吗)时却出现了问题,(这里应该就是为什么会耗时6小时的原因),因为数据的信息标记超出了磁盘的整个容量,(这会是什么原因造成的呢)三亿文库包含各类专业文献、中学教育、外语学习资料、各类资格考试、应用写作文书、幼儿教育、小学教育、13一次Linux下testdisk+gdisk恢复XFS文件系统及数据的经历等内容。 
 testdisk恢复删除的分区_电脑基础知识_IT/计算机_专业资料。1.为了顺利安装 test...Testdisk_PhotoRec数据恢... 6页 2下载券
一次Linux下testdisk+gd... 11页...  Linux下恢复丢失的分区_IT/计算机_专业资料。linux下...(sun solaris) \xfs(XFS 日志文件系统) 查找分区 ...分区表写入 sda 好了,这个软件叫 testdisk.很帅的...  Linux XFS文件系统描述观察及磁盘命令详解_计算机软件及应用_IT/计算机_专业资料...。。 w write table to disk and exit # 储存分区操作后离开 gdisk 不管你...  总述:基于 linux 系统,删除数据及格式化后的数据恢复方案 ◎ 基于 EXT2/EXT3/EXT4 文件系统; ◎ 基于 Reiserfs 文件系统; ◎ 基于 Xfs 文件系统 ◆ 检测流程...  你可以使用 xfs_info 命令行工具来 检查数据块大小和数量: 要将 XFS 文件扩展...Linux下XFS文件系统修复... 8页 1下载券
一次Linux下testdisk+gd... 11页...  PhotoRec 忽略文件系统,能直接从介质底层恢复数据,因此,在介质的文件系统严重破坏...一次Linux下testdisk+gd... 11页 免费
数据恢复的方法 暂无评价 46页 免费...  幸运的是,Linux 下提供了一款开源软件恢复误删的数 据,利用这个 ext3 文件系统数据恢复工具 ext3grep 可以恢复误删除的数据。 二、 ext3grep 的安装与使用 ext...  LINUX 上机实验报告_电子/电路_工程科技_专业资料。...xfs、ReiserF 其他文件系统: MX ...报告内存使用情况(以字节为单位) ,每5秒更新一次。...磁盘格式_百度百科
声明:百科词条人人可编辑,词条创建和修改均免费,绝不存在官方及代理商付费代编,请勿上当受骗。
windows下主要有FAT16、FAT32、NTFS 等,最新格式为,不同的磁盘格式有不同的特性。FAT格式基本上已经不再使用。linux下的格式为ext系列,ext4,ext3等。Mac OS X的硬盘格式是AHFS。exFAT(Windows Vista SP1及以上)单文件大小最大可达16EB(18 446 744 073 709 551 616字节,就是(理论值,16×TB),1TB=1024G),簇大小可高达32MB ,采用了剩余空间分配表,剩余空间分配性能改进 ,同一目录下最大文件数可达65 536个 。NTFS(Windows):支持最大分区2TB,最大文件2TBFAT16(Windows):支持最大分区2GB,最大文件2GBFAT32(Windows):支持最大分区124.55GB,除非不再使用“scandisk”,最大文件4GBHPFS(OS/2):支持最大分区2TB,最大文件2GBEXT2和EXT3(Linux):支持最大分区16TB,最大文件2TBEXT4(Linux):使用了B+树索引数据extent的文件系统(有别于EXT2/EXT3),支持最大分区1EB,最大文件16TBJFS(AIX):支持最大分区4P(block size=4k),最大文件4PXFS(IRIX):这是个正经的64位的文件系统,可以支持9E(2的63次方)的分区
磁盘格式exFAT
超过4GB的U盘时默认是,但是这种格式是很伤U盘的,因为NTFS分区是采用“日志式”的,需要记录详细的读写操作,肯定会比较伤闪盘芯片,因为要不断读写。
下面请看exFAT、NTFS、FAT分区的比较
Win 95 OSR2之后
Win2000之后
Win CE 6/Vista SP1
最大单一文件
2bytes-4GB
受最大分割容量
16EB(理论值)
2TB(但NT内核系统限制为32GB)
2TB~256TB(受MBR影响)
16EB(理论值)(支持到256TB)
至少可以大于1000
磁盘格式优势
1.支持非常大的文件和
2.对性能的改进支持
3.对未来的创新的可扩展性功能的支持
4.添加 Flash 媒体兼容性
磁盘格式劣势
:Windows版本要求高。
磁盘格式用途
exFAT原本设计的目的是在FAT32与NTFS之间取得一个折中,有FAT32的轻便、不需要耗损太多的效能及记忆体来处理文件运作,又有类似NTFS的CAL存取控制机制(很可惜在SP1下找不到exFAT对于CAL的支持),以及类似HPFS系统可快速整理可用丛集空间的Free Space Bitmap,来将档案破碎的情况尽量减少。 然而要真正比较出使用FAT32、NTFS及exFAT时的档案破碎情况很难做到客观的评比,剩下所能测试的就是存取效能了,尤其是exFAT最大的丛集大小达到了惊人的32MB,连NTFS都只有64KB,如果随身碟真的拿来存放BD Remux动辄上GB的大档案,那么将exFAT的丛集设大时,将会有多少效能增进呢? exFAT(Extended File Allocation Table)是适用于随身碟或随身型携带装置(如PDA)的新格式,最早出现在2006年的WinCE 6.0,为了增进与的相容性还有便于随身装置的同步需求,到了Vista SP1正式被纳入桌面操作系统所支持的档案系统,但跟一般玩家息息相关的,还是在于U盘上的应用。
磁盘格式区别
1、什么是NTFS-新(N)技术(T)文件(F)系统(S)?
想要了解NTFS,我们首先应该认识一下FAT。FAT(File Allocation Table)是“”的意思。对我们来说,它的意义在于对的管理。FAT16、FAT32、NTFS是目前最常见的三种文件系统。
FAT16:我们以前用的DOS、Windows 95都使用FAT16文件系统,常用的Windows 98/2000/ XP等系统均支持FAT16文件系统。它最大可以管理大到2GB的分区,但每个分区最多只能有65525个簇(簇是磁盘空间的配置单位)。随着硬盘或分区容量的增大,每个簇所占的空间将越来越大,从而导致硬盘空间的浪费。
FAT32:随着大容量硬盘的出现,从Windows 98开始,FAT32开始流行。它是FAT16的增强版本,可以支持大到2TB(2048G)的分区。FAT32使用的簇比FAT16小,从而有效地节约了硬盘空间。
NTFS:微软Windows NT的系列操作系统支持的、一个特别为网络和、等管理安全特性设计的磁盘格式。随着以NT为内核的Windows 2000/ XP的普及,很多个人用户开始用到了NTFS。NTFS也是以簇为单位来存储数据文件,但NTFS中簇的大小并不依赖于磁盘或分区的大小。簇尺寸的缩小不但降低了磁盘空间的浪费,还减少了产生的可能。NTFS支持文件加密管理功能,可为用户提供更高层次的安全保证。
2、什么系统可以支持NTFS文件系统?
只有Windows NT/2000/XP/Vista/7/8/10才能识别NTFS系统,Windows 9x/ Me以及DOS等操作系统都不能支持、识别NTFS格式的磁盘。由于DOS系统不支持NTFS系统,所以最好不要将C:盘制作为NTFS系统,这样在后便于在DOS系统下修复。
NTFS与操作系统支持情况如下:
FAT16 windows 95/98/me/nt/2000/xp unix,linux,dos
FAT32 windows 95/98/me/2000/xp/Vista/7/8/10
NTFS windows nt/2000/xp/Vista/7/8/10
3、我们需要NTFS吗?
Windows 2000/XP在文件系统上是向下兼容的,它可以很好地支持FAT16/FAT32和NTFS,其中NTFS是Windows NT/2000/XP/Vista/7/8/10专用格式,它能更充分有效地利用磁盘空间、支持文件级压缩、具备更好的文件安全性。如果你只安装Windows 2000/ XP/Vista/7/8/10,建议选择NTFS文件系统。如果,则(C盘)必须为FAT16或FAT32,否则不支持多重引导。当然,其他分区的文件系统可以为NTFS。
4、如何将FAT分区转换为NTFS?[1]
Windows 2000/XP提供了分区格式转换工具“”。Convert.exe是Windows 2000附带的一个DOS命令行程序,通过这个工具可以直接在不破坏FAT文件系统的前提下,将FAT转换为NTFS。它的用法很简单,先在Windows 2000环境下切换到DOS命令行窗口,在提示符下键入:convert 需要转换的盘符 /FS:NTFS。如系统E盘原来为FAT16/32,需要转换为NTFS,可使用如下格式:convert e: /FS:NTFS。所有的转换将在系统重新启动后完成。
此外,你还可以使用专门的转换工具,如著名的硬盘无损分区工具Powerquest Partition Magic 7.0,选择“Convert Partition”按钮,或者是从界面菜单条“Operations”项下拉菜单中选择“Convert”命令。激活该项功能界面。
在界面中选择转换输出为“NTFS”,之后单击“OK”按钮返回程序主界面。“Apply”添加设置。此后系统会重新引导启动,并完成分区格式的转换操作。
5、如何在NTFS格式分区下找回意外删除丢失的文件?
你可以使用专门的软件,如Final Data for NTFS,或者是Get Data Back for NTFS 1.04。这两个软件的文件恢复效果都不错。本人推荐使用Get Data Back for FAT 1.05/NTFS 1.04(是2个软件),使用它完成磁盘文件格式的转换也是非常容易的。
6、如果Windows 2000/XP/Vista/7/8/10安装在C盘(NTFS格式),当Windows崩溃时在DOS状态下不能进入C盘,怎么办?
你可以使用Windows 2000/XP/Vista/7/8/10的安装光盘启动来修复Windows,或者是制作Windows 2000/XP/Vista/7的安装启动应急盘。注意:Windows 2000的安装盘制作程序在程序的安装光盘中,而Windows XP的应急盘制作是独立提供的,需要从微软的网站下载。
7、Final Data for NTFS或Get Data Back for NTFS可以修复被意外格式化的硬盘吗?
这两个软件都可以恢复格式化删除的数据(除外)。常规格式化删除的只是数据信息,低级格式化则删除全部数据区,当硬盘技术还不像现在这样发达的时候,磁盘表面很容易磨损。硬盘使用者对经常出现的读错误,往往采用低级格式化。修复被格式化的硬盘,只能将这个硬盘拆下来,安装到其他的计算机中,之后执行文件修复操作。Final Data甚至可以修复由CIH病毒破坏的硬盘。
8、Windows 98(FAT系统)下如何直接读写NTFS文件系统
当电脑安装有Windows 98和Windows 2000/ XP两个操作系统,如何在FAT系统下直接读写NTFS文件系统?虽然FAT系统可以转换为NTFS系统,但是有时我们需要在机器中同时安装Windows 98和Windows 2000/XP。此时的麻烦就来了,由于Windows 98不能读取Windows 2000的NTFS,那么如何进行数据交换呢?实际上我们只需要使用一个小小的软件NTFS for Windows 98就可以让Windows 98轻松读取、甚至写入NTFS分区。首先,下载NTFS for Windows 98 1.07版(能读、写!)。安装结束后会出现一个配置界面,在该界面中的“NTFS System Files”项中需要设置的是程序可以借用的Windows 2000/XP系统的相关文件保存路径。由于读取NTFS文件系统必须使用到Windows 2000/XP的一些系统文件,所以事先需要在Windows 2000/XP下,将如下9个文件复制到FAT分区中的任意一个文件夹下,这些文件分别是:
NTFS.SYS:存谟凇磜innt〉system32drivers tfs.sys
NTOSKRNL.EXE:存在于〈winnt〉
system32 toskrnl.exe
AUTOCHK.EXE:存在于〈winnt〉
system32utochk.exe
NTDLL.DLL:存在于〈winnt〉system32 tdll.dll
C_437.NLS:存在于〈winnt〉system32&437.nls
C_1252.NLS:存在于〈winnt〉system32&1252.nls
L_INTL.NLS:存在于〈winnt〉system32_intl.nls
(注意:Windows XP的目录是WINDOWS,而不是WINNT,如果你是全新或升级安装的话)
在“Drive Letter Assignments”项中提供的设置是设置允许可以识别的NTFS分?谭??柚玫囊谰菘梢圆慰荚赪indows 2000/ XP下的盘符顺序。如果单击界面中的“Advanced”按钮,在关联界面中提供了针对设置的NTFS分区高级设置,其中包括设置为只读属性“Read-Only”、允许写入“Write-Through”。对于检查点间隔“Checkpoint Interval”和写回间隔“Writeback nterval”,使用程序提供的默认设置即可。到此设置完成,单击OK按钮保存设置并退出。重启后就可以在Windows98下访问NTFS分区了!
9、如何在DOS系统下直接读写NTFS文件系统?
Winternals Software LP 公司提供了工具软件解决了这个问题。用一张MS-DOS就可以作到以前不可能作到的事,修改,删除,更新 NTFS上的文件,实际 NTFSDOS pro 是在 Windows NT 出问题时的一个。
10、在NTFS系统下,如何保护自己的文件、文件夹?
由于NTFS文件分区格式具有良好的安全性,如果你不希望自己在硬盘中的文件被其他人调用或查看,使用权限控制方式加密是非常有效的方法。设置方法非常简单:以身份登录,使用鼠标右键单击需要加密的文件夹,选择“Properties”,切换到“Security”选项卡。在“Group of user names”项中设置允许访问的用户只有Administrator和自己。删除其他的所有用户。保存设置退出即可。此后,其他用户将不能访问该文件夹。使用这项功能需要注意的是:一定要保证只有你一个人知道Administrator密码,并并且设置其他用户不能属于Administrator。此外,你还可以详细的给每个用户设置权限,包括设置读取权限、写入权限、删除权限等,这样使用起来就更加灵活。你还可以设置权限,控制一个磁盘,或者只为自己使用,这样其他人就不能看到你的任何东西了。
.网易[引用日期]1596人阅读
Linux(8)
1.格式化:
mkfs -t xfs /dev/sda
2.硬盘挂载:
No.1: mkdir /sda
No.2:mount /dev/sda
No.3:mount /dev/sda /sda
查询是否成功: df -T
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11331次
排名:千里之外
原创:57篇
(6)(54)(5)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'xfs文件系统:格式化以及挂载 - CSDN博客
xfs文件系统:格式化以及挂载
  &源码& linux:3.14.56 xfsprogs:3.2.0
  &命令& mkfs.xfs -f /dev/[sdx] ; mount /dev/[sdx]; umount /dev/[sdx]
如情景所示,来分析分析,mkfs.xfs mount 以及umount操作都做了些什么事情。下述内容均为本人随意跟踪,看到那说到哪!仅作参考。
本例格式化xfs文件系统,有关xfs文件系统就不介绍了。倒是首先要分析mkfs.xfs命令,先得获取相应的源码,源码获取可到github搜索xfsprogs,之前找了一个util-linux的包,编译后才发觉不支持mkfs.xfs,其它的文件系统倒还支持一些的,可见xfs还是比较“特殊”的,值得了解一下。好吧,总之下载即可。
mkfs.xfs -f /dev/sdc
1、进入 xfs_mkfs.c文件主函数main。对于一个提供给用户使用的终端命令(或说控制接口),它做的事情无非就是在接受用户指令后,对相应指令参数进行解析,而后下发给后端进/线程做进一步处理,当然最终会返回信息给当前主进程,处理完事务后(同步的话),进程也就退出了。
while ((c = getopt(argc, argv, "b:d:i:l:L:m:n:KNp:qr:s:CfV")) != EOF) {
switch (c) {
force_overwrite = 1;
跟踪force_overwrite标志:
memset(&ft, 0, sizeof(ft));
get_topology(&xi, &ft, force_overwrite);
/1/ 首先初始化以ft为首地址的fs_topology结构体,那么不妨先来看看这个结构体的内容有哪些:
struct fs_topology {
/2/ 若ENABLE_BLKID有定义,即安装有blkid源码,即可执行blkid命令,获取设备的拓扑结构如下:
static void get_topology(
libxfs_init_t
struct fs_topology
force_overwrite)
if (!xi-&disfile) {
const char *dfile = xi-&volname ? xi-&volname : xi-&
blkid_get_topology(dfile, &ft-&dsunit, &ft-&dswidth,
&ft-&lsectorsize, &ft-&psectorsize,
force_overwrite);
if (xi-&rtname && !xi-&risfile) {
blkid_get_topology(xi-&rtname, &dummy, &ft-&rtswidth,
&dummy, &dummy, force_overwrite);
/2.1/ libxfs_init_t函数memset初始化为0,其成员变量disfile可知其初始化为0,又当前mkfs.xfs命令未加-d选项,则进入该分支处理。下面分支同理。
/2.2/ 处理获取设备拓扑结构,这里不好追踪就不展开了,关键函数定义实现在blkid命令源码中如:当前函数中的blkid_new_probe_from_filename。
/2// 若ENABLE_BLKID无定义,获取设备的拓扑结构:
static void get_topology(
libxfs_init_t
struct fs_topology
force_overwrite)
char *dfile = xi-&volname ? xi-&volname : xi-&
int bsz = BBSIZE;
if (!xi-&disfile) {
get_subvol_stripe_wrapper(dfile, SVTYPE_DATA,
&ft-&dsunit, &ft-&dswidth, &ft-&sectoralign);
fd = open(dfile, O_RDONLY);
if (fd &= 0) {
platform_findsizes(dfile, fd, &dummy, &bsz);
close(fd);
ft-&lsectorsize =
ft-&psectorsize =
if (xi-&rtname && !xi-&risfile) {
int dummy1;
get_subvol_stripe_wrapper(dfile, SVTYPE_RT, &dummy1,
&ft-&rtswidth, &dummy1);
/2.1// 不妨进入该函数:
get_subvol_stripe_wrapper(
*sectalign)
struct stat64
if (dev == NULL)
if (stat64(dev, &sb)) {
fprintf(stderr, _("Cannot stat %s: %s\n"),
dev, strerror(errno));
dm_get_subvol_stripe(dev, type, sunit, swidth, sectalign, &sb))
md_get_subvol_stripe(dev, type, sunit, swidth, sectalign, &sb))
----/2.1.1
if ( lvm_get_subvol_stripe(dev, type, sunit, swidth, sectalign, &sb))
if ( xvm_get_subvol_stripe(dev, type, sunit, swidth, sectalign, &sb))
if (evms_get_subvol_stripe(dev, type, sunit, swidth, sectalign, &sb))
/2.1.1// 分析它即可,其它的同理。顾名思义,即获取Multiple Devices相关的东西,也就是有关矩阵raid条带化的信息,因为mkfs.xfs命令未加-d选项,故而获取的是创建md设备时指定的条带信息。进入该函数可知,主要是对其参数进行赋值。
返回main主函数,调用libxfs_init函数进行xfs文件系统的初始化,主要关注一下函数:
 1、radix_tree_init
   基树初始化,主要用于内存管理,该树为典型的字典类型结构(有待研究)
 2、libxfs_device_open
   打开一个设备并且获取其设备号,即便不是真的设备亦返回一个伪设备号
 3、cache_init
   初始化缓存,返回cache结构体
 4、manage_zones
   manage_zones函数实现释放xfs分区或生成xfs分区。而生成启动xfs目录结构调用的是xfs_dir_startup函数,该函数定义在linux源码lib库中(可使得生成目录下”.”以及“..”文件)
回到main函数,进入判断force_overwrite标志位的分支结构,调用zero_old_xfs_structures函数,函数将置0初始化各个次要AG的sb超级块结构,通常128M至4T左右容量设的备,4个AG用于管理磁盘空间。当然若是raid阵列的话就另当别论了,相同容量需创建更多的AG。AG超级块结构参考:
回到main函数,调用libxfs_mount
—-/3/,该函数主要就是对结构体进行填充,不过却是非常重要的,不妨来看看:
xfs_mount_t *
libxfs_mount(
xfs_mount_t
xfs_sb_mount_common(mp, sb);
xfs_dir_mount(mp);
libxfs_readbuf
libxfs_putbuf
/3.1/ 首先要理解的是xfs_mount_t这个结构体类型,我们定义了一个用户层面上的xfs_mount结构体,同时方便了使用以XFS_*为前缀的宏。即该函数填充xfs_umount结构体,并将其返回,以供用户进程访问,也就是mkfs.xfs了。(注:即便设备上的文件系统格式化了,在未mount挂载前也是不能直接访问的)。而在进程使用完后,即在main函数最后,会调用libxfs_umount释放占用的资源(可理解xfs_mount为中间变量)。
/3.2/ 而该函数使用xfs_sb超级块的信息,建立了各类通用的mount挂载域
/3.3/ 顾名思义,
/3.4/ 填充好xfs_mount信息后,将其读取到相应的缓存区xfs_buf中
/3.5/ 而libxfs_putbuf –& cache_node_put,该函数将xfs_buf类型强制转化成cache_node类型,并添加至cache下发链表。最终使得以完成设备文件系统的格式化。
最后回到main函数,调用libxfs_getsb,同理该函数同样读取xfs_buf缓存中的内容,若读取出来的超级块信息与写入的相同,则标识文件系统格式化成功。到此,进程mkfs.xfs的整个执行流程也算是结束了,当然中间有很多东西都无视了(呵呵)
即将格式化xfs的磁盘挂载到相应目录
mount /dev/[sdx] /mnt
首先应用层shell实现系统调用sys_mount,而在本linux源码版本:调用SYSCALL_DEFINE5,申明定义在include/linux/syscall.h中。至于为什么使用这种方式定义sys_mount,实质上是为在64位的内核上实现调用32位的系统调用(有待研究)。
asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name,
char __user *type, unsigned long flags,
void __user *data);
函数sys_mount由SYSCALL_DEFINE5(5:代表参数个数)定义:
#define SYSCALL_DEFINE0(sname)
SYSCALL_METADATA(_##sname, 0);
asmlinkage long sys_##sname(void)
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
#define SYSCALL_DEFINEx(x, sname, ...)
SYSCALL_METADATA(sname, x, __VA_ARGS__)
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...)
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
__attribute__((alias(__stringify(SyS##name))));
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));
asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));
asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))
long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));
__MAP(x,__SC_TEST,__VA_ARGS__);
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
在内核中,结构体以及宏函数的使用可谓出神入化。有关这里的宏函数定义如何实现的,暂不展开,不好表达!
其实如下示:compat_sys_mount函数定义与上述SYSCALL_DEFINE5非常相似,而与sys_mount也似乎存在着某种联系(有待研究):
/include/uapi/asm-generic/unistd.h:
#define __NR_mount 40
__SC_COMP(__NR_mount, sys_mount, compat_sys_mount)
/0/ 上述的asmlinkage标识着调用函数参数的传递方式。若加该标识标识使用堆栈,缺省时使用的是寄存器传递函数参数。如:汇编中调用c函数,且使用堆栈传递函数,则在定c义函数时,需在函数前添加宏asmlinkage。需要注意的是内核只在系统调用时使用该宏,原因:一是,普通内核函数调用寄存器传参比堆栈传参快很多,想想就是无需解释。二是:对于系统调用时使用堆栈传参必然有其的合理性。有关第二点说到的合理性,不妨稍作解释,就不展开了:
  1,涉及到用户态与内核态的转换,转换过程实现需系统调用。也就是说系统调用函数既需访问用户态资源,与此同时访问内核资源。而内核与用户态的资源组织方式(可以这么说吧!)可是不同的,如:地址空间的映射方式就不同。
  2、有人说堆栈的信息来源不就是来自寄存器的copy吗,我想其实两者都能实现参数的传递,其本质不都是要实现压栈,现场保护吗。只不过用户态与内核态的转换,或说既要实现两者之间的通讯,又要实现两者的隔离。而毕竟内核态的东西使用用户态堆栈访问方式相当于做了一些隔离。在此可能真的牺牲了一些传参效率吧!(呵呵)。
下面不妨进入SYSCALL_DEFINE5函数定义,看看它做了些什么:
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
char *kernel_
struct filename *kernel_
char *kernel_
unsigned long data_
ret = copy_mount_string(type, &kernel_type);
if (ret & 0)
kernel_dir = getname(dir_name);
if (IS_ERR(kernel_dir)) {
ret = PTR_ERR(kernel_dir);
ret = copy_mount_string(dev_name, &kernel_dev);
if (ret & 0)
ret = copy_mount_options(data, &data_page);
if (ret & 0)
ret = do_mount(kernel_dev, kernel_dir-&name, kernel_type, flags,
(void *) data_page);
free_page(data_page);
kfree(kernel_dev);
putname(kernel_dir);
kfree(kernel_type);
/1/ 该函数将mount挂载的选项字符串内核的一个空闲页中,如下示:
int copy_mount_string(const void __user *data, char **where)
if (!data) {
*where = NULL;
tmp = strndup_user(data, PAGE_SIZE);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
/1.1/ 该函数最终调用copy_from_user函数,实现选项内容拷贝到指定空闲页中。需注意的是,该函数可睡眠,可能导致缺页情况。其中睡眠当然是针对当前进程而言的,若进程在copy_from_user或copy_to_user前被剥夺执行权限,而又在此期间触发了交换条件(参照:虚拟内存实现原理,交换通常发生在内存资源紧张时),则系统会将进程执行所需的相应资源从内存交换到硬盘中。之后当进程获得执行权限时,由于硬盘的资源只有在要使用的时候才加载到内存中(linux机制),因而即便是立即就加载数据到内存,进程也需阻塞睡眠等待。还有种情况就是,刚要加载数据时,进程又睡眠了,连数据加载操作都做不了。
/2/ 较新的内核版本均使用该函数,该函数与copy_mount_string函数不同之处在于:
int copy_mount_options(const void __user * data, unsigned long *where)
unsigned long
unsigned long
*where = 0;
if (!data)
if (!(page = __get_free_page(GFP_KERNEL)))
return -ENOMEM;
size = TASK_SIZE - (unsigned long)
if (size & PAGE_SIZE)
size = PAGE_SIZE;
i = size - exact_copy_from_user((void *)page, data, size);
free_page(page);
return -EFAULT;
if (i != PAGE_SIZE)
memset((char *)page + i, 0, PAGE_SIZE - i);
/2.1/ 函数最终调用__get_free_pages函数,返回一个32位的非高端页内存地址
/2.2/ 拷贝用户态数据不能超过TASK_SIZE(3G),超过3G已是属于内核态数据区域,故使用TASK_SIZE减出需拷贝的数据大小,更安全。
/2.3/ 调用exact_copy_from_user函数,较之于copy_from_user(返回值成功:0
失败:失败字节个数),最终能返回精确的copy数据大小。
/2.4/ 当拷贝数不足PAGE数据字节大小时,将未使用的页面数据区域设置为零
/3/ 该函数mount实现挂载文件系统的主战场,不妨进入该函数,看看都做了些什么?
long do_mount(const char *dev_name, const char *dir_name,
const char *type_page, unsigned long flags, void *data_page)
int retval = 0;
int mnt_flags = 0;
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
flags &= ~MS_MGC_MSK;
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
if (retval)
retval = security_sb_mount(dev_name, &path,
type_page, flags, data_page);
if (!retval && !may_mount())
retval = -EPERM;
if (retval)
goto dput_
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
if (flags & MS_NOSUID)
mnt_flags |= MNT_NOSUID;
if (flags & MS_NODEV)
mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC;
if (flags & MS_NOATIME)
mnt_flags |= MNT_NOATIME;
if (flags & MS_NODIRATIME)
mnt_flags |= MNT_NODIRATIME;
if (flags & MS_STRICTATIME)
mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
if (flags & MS_RDONLY)
mnt_flags |= MNT_READONLY;
if ((flags & MS_REMOUNT) &&
((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
MS_STRICTATIME)) == 0)) {
mnt_flags &= ~MNT_ATIME_MASK;
mnt_flags |= path.mnt-&mnt_flags & MNT_ATIME_MASK;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
else if (flags & MS_BIND)
retval = do_loopback(&path, dev_name, flags & MS_REC);
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
retval = do_change_type(&path, flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&path, dev_name);
retval = do_new_mount(&path, type_page, flags, mnt_flags,
dev_name, data_page);
path_put(&path);
/3.1/ 如该函数注释所诉:这些magic数使用于早些版本(2.4.0-test9以前),即无视MS_MGC_MSK与MS_MGC_VAL作用,通过从flags中获取,取反后写入flags,呵呵,意图很明显啊!。
/3.2/ 对于该函数memchr,就不展开了,它的作用是:在dir_name指向的内存区域中的前PAGE大小个字节中查找int=0的字符null,当第一次遇到该字符时停止查找,成功返回指向字符的指针;否则返回NULL。其实就是做了一下参数的检查,看指定数据内容是否存在。
/3.3/ 接下来,进入kern_path函数:
int kern_path(const char *name, unsigned int flags, struct path *path)
int res = do_path_lookup(AT_FDCWD, name, flags, &nd);
----/4.3.1/
*path = nd.
----/4.3.2/
/3.3.2/ 从kern_path和该行可知,函数只要实现将用户态path路径赋值到内核态路径,以便后续再内核态的操作。当然除此之外,要做的事情就是审核path的有效性了。如:对于某一块设备/dev/[sdx]而言,系统调用mount操作最终实现将一个可访问的块设备(该设备)安装到一个可访问的节点,即设备安装前就是要可访问的,也就是说在挂载之前,/dev/sdx已经与内核建立过相关的联系(nameidata结构体),而如上示/1/就将对其进行审核。
/3.3.1/ 该函数do_path_lookup –& filename_lookup,不妨来看看filename_lookup函数:
static int filename_lookup(int dfd, struct filename *name,
unsigned int flags, struct nameidata *nd)
int retval = path_lookupat(dfd, name-&name, flags | LOOKUP_RCU, nd);
----/4.3.1/
if (unlikely(retval == -ECHILD))
retval = path_lookupat(dfd, name-&name, flags, nd);
if (unlikely(retval == -ESTALE))
retval = path_lookupat(dfd, name-&name,
flags | LOOKUP_REVAL, nd);
if (likely(!retval))
audit_inode(name, nd-&path.dentry, flags & LOOKUP_PARENT);
----/4.3.2/
/3.3.1/ 路径查找函数,若/dev/[sdx]块设备存在,path_lookupat函数返回值retval=0,使nd有效(一系列操作将其初始化为正真的设备并与/dev/[sdx]比较该设备是否存在)。该函数返回0,do_path_lookup返回值ret为0,kern_path返回值为0
/3.3.2/ if (likely(!retval)) 等价于if (!retval),即进入分支对inode挂载节点进行审核,使得最终kern_path获取挂载点(nd的dentry域)。
安全性检查
最终返回到do_mount,而后根据参数flags的值来决定调用:do_remount
do_loopback
do_change_type
do_move_mount
do_new_mount其中的某一函数。下面以do_new_mount来简单介绍一下:
/3.5/ 进入该函数:
static int do_new_mount(struct path *path, const char *fstype, int flags,
int mnt_flags, const char *name, void *data)
struct file_system_type *
struct user_namespace *user_ns = current-&nsproxy-&mnt_ns-&user_
struct vfsmount *
if (!fstype)
return -EINVAL;
type = get_fs_type(fstype);
----/4.5.1/
if (!type)
return -ENODEV;
if (user_ns != &init_user_ns) {
if (!(type-&fs_flags & FS_USERNS_MOUNT)) {
put_filesystem(type);
return -EPERM;
if (!(type-&fs_flags & FS_USERNS_DEV_MOUNT)) {
flags |= MS_NODEV;
mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
mnt = vfs_kern_mount(type, flags, name, data);
----&/4.5.2/
if (!IS_ERR(mnt) && (type-&fs_flags & FS_HAS_SUBTYPE) &&
!mnt-&mnt_sb-&s_subtype)
mnt = fs_set_subtype(mnt, fstype);
put_filesystem(type);
----/4.5.3/
if (IS_ERR(mnt))
return PTR_ERR(mnt);
err = do_add_mount(real_mount(mnt), path, mnt_flags);
----/4.5.4/
mntput(mnt);
/3.5.1/ 该查看内核是否注册了参数fstype所指的文件系统,get_fs_type会将参数fstype字符串跟内核链表中所有已经注册的文件系统结构体file_system_type的name成员向比较,若已注册则返回file_system_type结构体。
/3.5.2/ 该函数成功返回vfsmount结构体,内核中代表挂载文件系统的vfsmountt结构体填充成功。
/3.5.3/ 该函数执行在vfs_kern_mount函数后,将文件系统模块使用量减1。
/3.5.4/ 将新挂载的文件系统(由vfsmount表示)添加到系统的命名空间结构体的已挂载文件系统链表中,命名空间是指系统中以挂载文件系统树,每个进程的PCB中都有namespace成员来表示该进程的命名空间,大多数的进程共享同一个命名空间,所以如果在一个进程中将磁盘挂载到系统中,在另一个进程也是可以看到的,这就是由命名空间来实现的。vfsmount添加到相应的namespace中的vfsmount链表成功后do_new_mount返回。
这样从sys_mount到vfs_kern_mount到mount(有些版本为get_sb)再到具体的文件系统层调用xfs_fs_mount进行处理,处理完层层返回,内核也就实现了指定文件系统的磁盘挂载到指定目录。总体感觉在这个过程中内核主要实现vfsmount结构体的填充,而这个结构体中最重要的是super_block的填充,然后将vfsmount添加到相应进程PCB的namespace成员所指向的namespace结构体中,大部分进程都指向这个namespace,所以挂载后对大部分进程都是可见的。
即卸载格式化xfs文件系统的挂载点
umount /dev/sdc /mnt
系统调用sys_umount,而该函数使用SYSCALL_DEFINE2定义实现。首先不妨看看整个系统调用,umount实现的调用流程:
sys_umount()
--& SYSCALL_DEFINE2()
--&do_umount --& security_sb_umount --& sb_umount --& mq_put_mnt --& kern_unmount
SYSCALL_DEFINE2()
--&do_umount
--& security_sb_umount
--& umount_begin (统一接口)
--& fuse_umount_begin(fs/fuse/inode.c) --& fuse_abort_conn --& ... ...
--& mq_put_mnt
--& kern_unmount
--& mntput
--& mntput_no_expire()
--& deactivate_super()
--& deactivate_locked_super()
--& kill_sb()
.kill_sb = kill_block_super
(在fs/xfs/xfs_super.c中申明,注:在此有声明,但定义在fs/super.c中)
--& kill_block_super()
--& generic_shutdown_super()
--& put_super()
映射至 ==& xfs_fs_put_super
--& xfs_fs_put_super()
--& xfs_unmountfs()
--& xfs_ail_push_all_sync()
--& schedule()
一般来说,获取资源会比释放资源的处理过程要复杂一些的,那么可以说umount处理流程会简易一些吗?进到SYSCALL_DEFINE2函数中去看看吧!
SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
struct mount *
int lookup_flags = 0;
if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
return -EINVAL;
if (!may_mount())
return -EPERM;
if (!(flags & UMOUNT_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW;
retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
if (retval)
mnt = real_mount(path.mnt);
retval = -EINVAL;
if (path.dentry != path.mnt-&mnt_root)
goto dput_and_
if (!check_mnt(mnt))
goto dput_and_
if (mnt-&mnt.mnt_flags & MNT_LOCKED)
goto dput_and_
retval = -EPERM;
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
goto dput_and_
retval = do_umount(mnt, flags);
dput_and_out:
dput(path.dentry);
mntput_no_expire(mnt);
/1/ 查找挂载点
/2/ real_mount(path.mnt) –& container_of(mnt, struct mount, mnt)有关container_of宏,该宏可利用结构体中的某一成员变量的首地址计算出整个结构变量的地址。在这里,我们想给mount结构的指针变量赋值,即可通过使用path结构体中定义的指针变量path.mnt作为real_mount参数。上述第一个mnt为mount结构体中的一个vfsmount类型成员变量的首地址,而第二个mnt其实是mount结构体成员变量(类型当然也是为vfsmount)。
/3/ 该函数时umount的主战场:
static int do_umount(struct mount *mnt, int flags)
struct super_block *sb = mnt-&mnt.mnt_
retval = security_sb_umount(&mnt-&mnt, flags);
if (retval)
if (flags & MNT_EXPIRE) {
if (&mnt-&mnt == current-&fs-&root.mnt ||
flags & (MNT_FORCE | MNT_DETACH))
return -EINVAL;
lock_mount_hash();
if (mnt_get_count(mnt) != 2) {
unlock_mount_hash();
return -EBUSY;
unlock_mount_hash();
if (!xchg(&mnt-&mnt_expiry_mark, 1))
return -EAGAIN;
if (flags & MNT_FORCE && sb-&s_op-&umount_begin) {
sb-&s_op-&umount_begin(sb);
if (&mnt-&mnt == current-&fs-&root.mnt && !(flags & MNT_DETACH)) {
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
down_write(&sb-&s_umount);
if (!(sb-&s_flags & MS_RDONLY))
retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
up_write(&sb-&s_umount);
namespace_lock();
lock_mount_hash();
if (flags & MNT_DETACH) {
if (!list_empty(&mnt-&mnt_list))
umount_tree(mnt, 2);
retval = 0;
shrink_submounts(mnt);
retval = -EBUSY;
if (!propagate_mount_busy(mnt, 2)) {
if (!list_empty(&mnt-&mnt_list))
umount_tree(mnt, 1);
retval = 0;
unlock_mount_hash();
namespace_unlock();
/1.1/ 函数do_umount –& security_sb_umount –& sb_umount –& selinux_umount 顾名思义,是在安全的模式下做一些操作,那该函数是用来实现在安全模式下完成umoun卸载的任务吗?分析可知,其实这个函数只是通过获取一些信息(参照:superblock_has_perm函数)进而来评估,在当前环境能否顺利的完成umount操作。若不能则返回retval&0的数,umount任务取消。反之,继续。
/1.2/ 进入该分支说明MNT_EXPIRE置位为1了,即挂载时效到期(挂载时间到期感觉不好理解,把它当做普通标志位理解即可)
/1.3/ 中途返回说明umount失败,这里表示:若当前挂载点知进程的根目录或某进程使用强制手段卸载节点,再或是MNT_DETACH置位(该参数置位的话,将不会立即执行umount操作,会等挂载点退出忙碌状态时再操作),均立即返回操作失败。
/1.4/ 检查vfsmount的引用计数是否为2 若不为2则umount失败立即返回,计数2代表的是当前vfsmount结构的父vfsmount结构体,以及sys_mmount()对本对象的引用,而简单的可以理解就是:在文件系统卸载的时候不能再有额外的引用,想想也是!
/1.5/ 设置vfsmount对象mnt_expiry_mark字段为1
/1.6/ umount_begin该函数正式开始处理umount事务。umount_begin –& fuse_abort_conn 该函数用于终结所有与挂载点的链接如:IO链接等
void fuse_abort_conn(struct fuse_conn *fc)
spin_lock(&fc-&lock);
if (fc-&connected) {
fc-&connected = 0;
fc-&blocked = 0;
fc-&initialized = 1;
end_io_requests(fc);
end_queued_requests(fc);
end_polls(fc);
wake_up_all(&fc-&waitq);
wake_up_all(&fc-&blocked_waitq);
kill_fasync(&fc-&fasync, SIGIO, POLL_IN);
spin_unlock(&fc-&lock);
到此告一段落,其中有很多地方还有待学习,
本文已收录于以下专栏:
相关文章推荐
mkfs -t xfs /dev/sda
2.硬盘挂载:
No.1: mkdir /sda
No.2:mount /dev/sda
No.3:mount /dev/sda /s...
Linux系统的一般的文件系统名称类似于/dev/sda1或/dev/hda1,但是今天在进行系统维护的时候,利用df -h 命令敲出了/dev/mapper/VolGroup-lv_root和/de...
由于redhat系统不再期官网注册,系统安装完成之后无法正常使用期yun源,因此更改redhat的yum源为CentOS的源
root@linuxprobe[06:22:1...
下面将介绍如何创建xfs文件系统,分配配额以及对其扩容:
######################################################################...
Keystone认证服务
Keystone认证服务中的概念
Keystone的验证过程前文列表Openstack组件部署 — Overview和前期环境准备
Openstack...
fdisk -l   #查看硬盘挂在情况
Disk /dev/xvda: 21.5 GB,
255 heads, 63 sectors/track, 2610 c...
linux硬盘分区及LVM使用流程
以前没接触过CentsOS 7 ,对其所改变的特性不了解,偶然在centos 7中接触到LVM,创建LVM的方法和6中没有区别,但是对LVM进行扩容就有点不一样了,使用以前的方法进行扩容后始终没有生效...
一、涉及到的几个组件1.1、apache     —— 它是Apache软件基金会的一个开放源代码的跨平台的网页服务器,属于老牌的web服务器了,支持基于Ip或者域名的虚拟主机,支持代理服务器,支持安...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 mac下移动硬盘格式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信