NTFS格式硬盘pe系统无法读取硬盘,是新系统的BUG么

4234人阅读
C/C++(21)
错误排查(5)
这事情还得从上上星期说起。最近在跑一个自己写的数据挖掘程序,这程序要跑上两三天,期间要同时向磁盘输出一个220多GB的二进制文件(以下称文件1)和一个450多GB的二进制文件(以下称文件2)。我上上周三就把程序写好了,用的是std::ofstream。 程序跑了两天,到了上上周五早上,我欢欢喜喜地去上班,准备收结果。谁知到了办公楼下,在配电箱上卖力捣腾的电工扭头看见我,对我说:“停电了。”——这段时间单位在进行电路的整改,不过停电还真是我没料到的事。于是茫然地跑进办公室,发现除了我自己写的程序外,电脑上的所有程序所有窗口居然还在运行着!根据运行日志,我的程序是在64%进度因为对文件1的ofstream::write操作出错而停下的。大惑不解——我的办公室到底有没有停电?莫非刚才只停电了一秒不到,而我的外星人台式机强劲到竟能在短暂瞬间的停电下继续工作,只是密集的磁盘操作会受影响? 正准备再花两三天时间跑一次程序。谁知朱老板实验室那边传来消息,说是我写的另一个软件——GMDR-GPU在分析一个大数据时崩溃,而重现错误似乎也要一两天时间。无奈,只有先暂停这边的程序,放下这边的工作,双休日加班,处理朱老板那边遇到的bug。 还好到了上周一,朱老板那边的bug也修复了。于是重新开始跑程序。这回我跟电工打了招呼,要他别停我房间的电。谁知到了周三,我在电脑前吃早餐的时候,听见机箱风扇高速飞转的声音突然消失。一颗心马上提起来,立即给屏幕解锁进入系统。果然,我的程序又出错了——这回是在63%进度对文件2的ofstream::write操作出错。 怎么回事?我再次困惑了。几秒钟之后,我听见中央空调“嘀”地一声响——原来电工又在对配电箱进行开闸合闸的操作。这时一个念头闪过:会不会是电压不稳对密集的磁盘操作有影响?于是问电工:刚才的电压会不会不稳?电工说:中央空调的启动和关闭可能会使电压稍微有些波动,但一般情况下电压应该是稳的。文件大小有限制?我之前查过的,NTFS支持的文件大小远远超过4GB,而且我这是64位程序;况且如果是文件大小限制在4GB的话,应该1%不到就出错了,程序运行到64%的话都已经写了一两百GB了。不过为了确认,我还是写了个小程序,将700GB的double输出到一个文件中。结果证实了我的想法:程序运行了约两个小时,成功输出了700GB的文件。我也写了另外一个小程序,读这700GB的文件,确认了里面的内容是正确的。于是只好准备又将程序重新运行一遍——没办法的办法。这时已经是上周三。不过在此之前得对程序做些改动,想办法让它在出错的情况下能输出更详细的错误信息。记得C++的流对象有几个成员,好像是bad()和fail()什么的,可以用来判断流对象当前的有效状态。于是查到了basic_ios类。ofstream继承ostream,ostream是basic_ostream模板的特化,basic_ostream继承basic_ios。basic_ios有三个成员函数可以判断流对象当前的有效状态:bad():Indicates a loss of integrity of the stream buffer.fail(): Indicates failure to extract a valid field from a stream.good(): Indicates the stream is in good condition.看来fail()只会在输入流上返回真,而good就是!(bad || fail)。我的程序出错时ofstream肯定是处于bad状态,可这并不能告诉我多少有用的信息。我需要知道更具体的出错原因。于是上网搜索,看看有没有其他人用ofstream::write时同样出错,看看有没有办法输出更详细的出错原因。然后得知可以用C语言的errno。于是赶紧在程序中加入对errno的输出,重新跑。我心里面一直嘀咕着:如果是程序本身的错误,那会是什么错误呢?单元测试都通过了;内存访问异常也不会这么报错;磁盘空间也够的。会不会是程序的其它地方出现了内存访问越界,正好访问破坏了ofstream对象?真要是那样的话,这bug可就太难定位了。这是我第一次碰到写文件错误,还是这么棘手的错误。 趁着跑程序的空档,我在CSDN上发帖求助:在Stack Overflow上也发帖求助:两个帖子逐渐得到回复,然而大家也不太清楚是怎么回事。有人建议用本地API,这倒是我早就想到的。但我的程序有跨平台要求,过一段时间还要在Linux下运行,可能的话还是想尽量用标准C++。不过CSDN网友说:“既然你说写单个文件没问题,那要是把两个文件分开写呢,我是说不要同时写。”这倒是我没想到的。唔,如果这第三遍跑还出错的话,那就采纳ri_aje的建议。不过我想写完一个文件再写另一个文件肯定是没问题的,而且由于算法和计算资源的限制,我的实际程序必须要同时写两个文件。所以届时我打算单独写一个小程序,同时写两个文件。如果这个小程序出现同样错误的话,那就可以排除实际程序中其它地方出错的可能性了。 结果这回正在跑第三遍的程序真的又出错了!而且这回才运行到55%就出错,并且仍然是在文件2上调用ofstream::write出错。errno给出的错误状态码是EINVAL: Invalid argument。于是马上写了一个类似下面的小程序,同时写两个文件——一个220GB左右,另一个450GB左右:#include &fstream&
#include &iostream&
int _tmain(int argc, _TCHAR *argv[])
    const TCHAR *fileName1 = _T("file1.bin"),
*fileName2 = _T("file2.bin");
    const unsigned __int64 numElems = ;
    ofstream file1(fileName1, ios::binary);
    if (!file1)
        cerr && "Failed to create file " && fileName1 &&
        exit(1);
     ofstream file2(fileName2, ios::binary);
     if (!file2)
     {
         cerr && "Failed to create file " && fileName2 &&
         exit(1);
     }
     for (unsigned __int64 cnt = 0; numElems & ++cnt)
     {
         const void *pV = 0;
         const float valueFloat = static_cast&float&(cnt);
         pV = &valueF
         if(!file1.write(static_cast&const char *&(pV), sizeof(valueFloat)))
        {
             cerr && "errno: " && errno && ": " && strerror(errno) &&
            cerr && "Write error on file1!" &&
            exit(1);
        }
        const double valueDouble = static_cast&double&(cnt);
        pV = &valueD
        if(!file2.write(static_cast&const char *&(pV), sizeof(valueDouble)))
        {
            cerr && "errno: " && errno && ": " && strerror(errno) &&
            cerr && "Write error on file2!" &&
            exit(1);
        }
    cout && "Done." &&
    return 0;
} 结果经过5个多小时,这个程序运行到64%进度的时候,出现了同样的错误!(题外话,这里我注意到一个细节:同样是用ofstream向磁盘输出700GB的文件,输出成单个文件只需要2小时;而输出成两个文件,运行到64%却经过了5个多小时,也就是说如果运行成功的话需要10个多小时。) 这么说肯定是程序本身的bug了,不过幸运的是,可以排除是程序其它地方出错了。Invalid argument,无效的参数。可是我盯着程序中调用ofstream::write的地方,盯了很久,非常确定传给ofstream::write的参数是合法的。不过errno是C语言的机制,只有当C语言库函数出错时,errno才会被设置。ostream::write很可能是调用了C标准库的fwrite,可能是调用fwrite时传入了非法的参数。这么说这很可能是微软的STL实现中的bug。 于是跑到Visual Studio的安装目录里,将fstream、ostream等各个头文件打开来研究。C++模板的一个额外好处在这里便体现出来了——要想将模板给人用的话,必须给源代码。果然,ofstream::write在多处调用了fwrite,这也是ofstream::write唯一会调用的C标准库函数。不过我也盯着那些fwrite看了很久,觉得传入那些fwrite的参数也不太可能是非法的。为此我甚至还修改了fstream文件,在其中一处唯一让我有一点点怀疑的fwrite的出错处理语句中加入了自己的打印语句,然后将小程序又运行了一遍。结果小程序并没有执行我的打印语句,这证明ofstream::write对fwrite的各个调用也没有传入非法参数。那到底是咋回事呢?先不管三七二十一,我觉得这八成应该是微软STL实现的bug,于是向微软提交了一份bug报告,然后继续研究,心想微软对标准的实现果然是不给力么:现在只有改用Win32本地API——CreateFile和WriteFile了。于是花了一些时间改动那个小程序。不过改好之后,刚一运行,就发现程序的速度慢了很多很多:运行到1%就需要半小时,这么说全部运行完还得2天多!我想是因为我没有在程序中设计缓存,每次调用WriteFile的时候只是写一个float或一个double,所以调用了很多次WriteFile;而每次调用WriteFile时,程序都要在用户态和内核态之间切换;另外磁盘的数据传输能力也没有被充分发挥,这当然慢了。于是再次改动小程序,设计缓存,每次写16KB。这下小程序快多了,而且用2小时就运行到了50%,也就是说比用ofstream的版本快上了一倍不止。 这次,小程序成功运行到了100%,将两个文件输出完毕。唔——看来应该就是微软的ofstream::write实现有bug了!不过我读ofstream::write的代码读了半天也没发现bug,还是让微软的专家们自己找去吧。那么要不要在实际的程序中用CreateFile和WriteFile呢?我衡量了一下:不如试验一下直接用FILE指针、fopen和fwrite。如果C标准库函数没问题的话,还是用C标准库函数的好,这样可移植性好。我想C标准库函数应该没问题。于是又花了点时间,把小程序改成用FILE *、fopen和fwrite。由于之前用CreateFile和WriteFile的过程也让我想起了Win32的GetLastError()函数,因此这回我在小程序里也加入了出错时对GetLastError()函数的调用——毕竟Win32的错误代码比errno给出的信息要详细多了。另外我还加入了对ferror()的调用。 谁知结果大大出乎我的意料:这回程序又在64%出错了!errno仍然是EINVAL: Invalid argument;ferror()返回的是EPIPE:Broken pipe;GetLastError()返回的是665:ERROR_FILE_SYSTEM_LIMITATION:The requested operation could not be completed due to a file system limitation。 ferror()的信息没什么用处,估计意思是FILE结构体损坏了。还是将GetLastError()的返回值ERROR_FILE_SYSTEM_LIMITATION作为线索,在网上搜索吧。结果正是这个线索让我找到了错误的真正原因!原来这bug既不是藏在我的程序上,也不是藏在微软的C标准库或C++标准库实现中,而是藏在了NTFS中:如果程序同时向磁盘写两个大文件,那这两个文件就会被分割成大量的碎片;而在NTFS中,如果一个文件被分割成大量碎片,这个文件的大小就会受到限制。以下是微软帮助和支持给出的技术解释(见刚才给出的网址): When a file is very fragmented, NTFS uses more space to save the description of the allocations that is associated with the fragments. The allocation information is stored in one or more file records. When the allocation information is stored in multiple file records, another structure, known as the ATTRIBUTE_LIST, stores information about those file records. The number of ATTRIBUTE_LIST_ENTRY structures that the file can have is limited. 翻译(微软帮助和支持的机器翻译真没法看):当一个文件被分割成大量碎片时,NTFS就需要用更多的空间来存储这些碎片在硬盘中的分配信息。这些分配信息被存储为一个或多个文件记录。当这些分配信息被存储为多个文件记录时,NTFS就会用另一个数据结构——ATTRIBUTE_LIST来存储这些文件记录的相关信息,而一个文件能拥有的ATTRIBUTE_LIST_ENTRY结构体的数量是有限的。 我下载了工具来查看那两个才写了一半的文件。果然,文件中的碎片数量已经达到了几百万之多!于是按照微软帮助和支持的说明,我下载安装了补丁,还下载安装了商业软件的试用版。打了补丁后还得将800多GB的E盘格式化,我勒了个去……格式化后,我先把Diskeeper开了起来,然后运行用fwrite的小程序。哇塞,速度比原来快了一倍多,Diskeeper真是给力——我后来试了一下不开Diskeeper,速度跟一开头没打补丁时是一样的。当然,重要的是——经过5个多小时,小程序成功运行完毕了!再用Contig查看一下两个文件,碎片数量才几万。既然fwrite成功了,那么ofstream应该也能行;而且既然微软已经发步了解决这个问题的补丁,那么不开Diskeeper应该也行。于是我又换回了用ofstream的版本。结果没想到不开Diskeeper的ofstream比开了Diskeeper的fwrite还快——3小时就成功运行完毕了。看来ofstream对缓存的管理比fwrite要好么。再用Contig查看,碎片数量果然又恢复成几百万了。于是,终于解决了这个困扰我一个多星期的问题。这时已经是5月1日,也就是昨天了。总结写程序的时候,如果要对调用错误进行检查并输出错误信息,那么要利用库和系统自身设计的错误信息机制,如C标准库的errno和Windows系统的GetLastError()。这些信息会对查错提供很大的帮助。如果我一开始就用了errno和GetLastError(),那就能早几天解决这个问题了。如果要往磁盘写大量的数据,尽量将这些数据合并成一个文件写,而不是分开多个文件写。这样一来可以减少文件碎片,二来可以加快写文件的速度。NTFS硬盘文件格式的使用注意事项_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
NTFS硬盘文件格式的使用注意事项
你可能喜欢【原创】【技术贴】关于MAC OS X系统没法读写NTFS格式的笨方法和移动硬盘无法识别读写问题的解决方法!(求加分。。。)
注册时间 最后登录
在线时间9 小时 UID
主题帖子人气
小苹果, 积分 24, 距离下一级还需 26 积分
最近几天陆续有很多盆友遇到了这类问题
就是MAC OS X系统不能识别或者不能读写移动硬盘
有个朋友问我啊,怎么回事啊东西拉不进去只能弄出来也删不掉里面的东
西,还有的都不能识别所以我想发个技术贴~不知道有没有人发过了
不过我发一下造福大众嘛!~~~~~~~~~~~~~华丽丽的分割线~~~~~~~~~~~~~~~
1.首先是磁盘无法识别的问题
相信有些朋友已经遇到这种问题了
实际上都是NTFS没法读写的问题 有个软件可以读写的 不过我觉得还是用WIN和MAC OS X都能读写的ExFat格式比较好 仁者见仁吧。。。
移动硬盘插入后并没有显示出盘符,然后MAC的磁盘工具可能会跳出来跟你说,无法识别
不要急不要慌~万物生长靠阳光~
下面我们要进行的是格式化磁盘的工作,改变它的属性
也就是MAC OS X能识别的硬盘属性,所以在这之前最好找个WIN系统的电脑对盘内文件做下备份
(因为没有有问题的盘就没办法截图了。。。)
我们来单击一下【初始化...】这个键
好的,你会看见磁盘工具跳出来了如下图
这时你会看见左上方有你的未识别的磁盘的盘符
点击任意一个都行 一般都是你的盘下面是分区
点击【抹掉】就出现下面这俩玩意~
然后点击下面的格式
会跳出来好多,点击{ExFat}这个格式
想重命名就重命名一下~
再点击下面的【抹掉】
等会就OK了~
如果不想那么麻烦,有条件的直接在WIN系统里面格式化
也是选择ExFat格式的格式化就行了
2.关于无法读写问题
其实和上面那个问题性质都是差不多的
因为目前我知道的WIN系统和MAC OS X系统的能共同读写的一种磁盘格式就是【ExFat】格式
所以,我的方法是:将移动硬盘重要文件备份后,格式化为ExFat格式
具体方法请参照上面方法【1】~
我也是新手啊,大神勿喷。。。(图已补上)
<p id="rate_0577" onmouseover="showTip(this)" tip="威锋有你更精彩:)&人气 + 1
" class="mtn mbn">
威锋有你更精彩:)
注册时间 最后登录
在线时间9 小时 UID
主题帖子人气
看来是我OUT了。。。这不算2L。。。这是留楼用的。。。
注册时间 最后登录
在线时间9 小时 UID
主题帖子人气
我桑心了。。。果然我的是最笨的办法。。。
注册时间 最后登录
在线时间1300 小时 UID
主题帖子人气
注册时间 最后登录
在线时间1771 小时 UID
主题帖子人气
macbook pro MD313
这个方便嘛
macbook pro MD313
注册时间 最后登录
在线时间1645 小时 UID
主题帖子人气
留名。。。。Z
注册时间 最后登录
在线时间12 小时 UID
主题帖子人气
感谢LZ分享。作为刚入了air、移动硬盘还在路上的超级白,还以为硬盘查哪个系统都是直接能读的T.T
注册时间 最后登录
在线时间470 小时 UID
主题帖子人气
这个才是华丽的技术贴嘛~很容易就解决了~
注册时间 最后登录
在线时间1489 小时 UID
主题帖子人气
对pkmao6于 15:51在楼主发表的主题评分:人气:+1;
最近几天陆续有很多盆友遇到了这类问题
就是MAC OS X系统不能识别或者不能读写移动硬盘
有个朋友问我啊,怎么回事啊东西拉不进去只能弄出来也删 ..威锋有你更精彩:)
注册时间 最后登录
在线时间43 小时 UID
主题帖子人气
学习了,但不知道格式改后对盘今后的使用有什么影响么
您需要登录后才可以回帖
回帖后跳转到最后一页
丨 粤ICP备号-10 丨 新三板上市公司威锋科技(836555)
增值电信业务经营许可证:
Powered by Discuz!
(C) Joyslink Inc. All rights reserved 保留所有权利42被浏览13,171分享邀请回答2820 条评论分享收藏感谢收起0添加评论分享收藏感谢收起你们是怎么解决mac os系统 不能读写NTFS格式的????
注册时间 最后登录
在线时间21 小时 UID
主题帖子人气
小苹果, 积分 48, 距离下一级还需 2 积分
你们是怎么解决mac os系统 不能读写NTFS格式的???? 会不会有什么风险&&会不会造成死机??
注册时间 最后登录
在线时间1009 小时 UID
主题帖子人气
Paragon NTFS for Mac OS X
价格不贵,还实惠
注册时间 最后登录
在线时间727 小时 UID
主题帖子人气
Paragon NTFS for Mac OS X
有钱买正版,没钱直接找破解吧,少年。
注册时间 最后登录
在线时间20 小时 UID
主题帖子人气
Paragon NTFS
注册时间 最后登录
在线时间453 小时 UID
主题帖子人气
购买了Paragon
注册时间 最后登录
在线时间507 小时 UID
主题帖子人气
paragon NTFS啊
注册时间 最后登录
在线时间6206 小时 UID
帖子 精华10
主题帖子人气
任何技术性求助的PM一
错了吧,是能读不能写
所有PM已被屏蔽,所以别做无意义的事。
注册时间 最后登录
在线时间79 小时 UID
主题帖子人气
提示: 作者被禁止或删除 内容自动屏蔽
注册时间 最后登录
在线时间31 小时 UID
主题帖子人气
Paragon !
注册时间 最后登录
在线时间306 小时 UID
主题帖子人气
Paragon NTFS for mac破解版你可以实现对对NTFS——Windows PC的主要文件系统——提供极少支持。您无法在NTFS分区中创建、删除或者修改文件或文件夹,而仅仅只能读取。通过Paragon的 Mac OS X专用NTFS,您可以在Mac OS X下全读/写访问NTFS的任何分区。
  NTFS for Mac一直是Mac OS平台上最受欢迎的NTFS硬盘格式读取工具,有了NTFS for Mac,安装了双系统的Mac用户可以在OS X系统下直接读取和写入windows系统下的NTFS硬盘格式,解决了双系统下,硬盘格式互相不兼容的问题。但是NTFS for Mac作为一款商业软件,其正版软件一直都需要花费不小的金额来购买序列号进行激活,今天PC6小编就教各位如何免费获取NTFS for Mac的正版序列号的方法。
  1、此次Paragon公司推出NTFS for Mac免费计划,针对个人用户,您只需要前往NTFS for Mac 12 Special Edition 版本注册页面就可以注册成为NTFS免费计划的一员。
可以浏览这里的贴子
<p id="rate_12591" onmouseover="showTip(this)" tip="&a
href=&forum.php?mod=redirect&goto=findpost&ptid=8278772&pid=&fromuid=1&&&span &感谢分享^_^&/span&&/a&&人气 + 5
" class="mtn mbn">
您需要登录后才可以回帖
回帖后跳转到最后一页
丨 粤ICP备号-10 丨 新三板上市公司威锋科技(836555)
增值电信业务经营许可证:
Powered by Discuz!
(C) Joyslink Inc. All rights reserved 保留所有权利

我要回帖

更多关于 pe系统无法读取硬盘 的文章

 

随机推荐