ページ 11

ReadFileとWriteFile関数について

Posted: 2012年11月14日(水) 15:20
by needsueda
 ディスクの読み書きの件で意見を求めるトピックを建てたことで 
CreateFileの話が出ました。
そこで改めてCreateFileやReadFile,WriteFileを、マイクロソフト社のWEBで調べて見ました。
私が普段使っているVC6++とは違いVC++2005以降では
ファイルアクセスの仕方が大幅に変更されていることが判明しました。
前回のトピックが何度探しても判らないし、大事な事なので 新規にトピックを建てることにしました。

 VC++2005のマイクロソフト社の解説に以下の部分が追加されていました。
ReadFile WriteFile
WEB原文通り
・ファイルアクセスは、ボリュームのセクタサイズの整数倍のバイトオフセットの位置で開始しなければなりません。
・ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければなりません。
 たとえば、セクタサイズが 512 バイトの場合、512 バイト、1,024 バイト、2,048 バイトの読み書きはできますが、
 335 バイト、981 バイト、7,171 バイトなどの読み書きはできません。

 ご指摘の通り、私もopenもしくは_openは、CreateFileに自動的置き換えられていると理解して来ましたが
この調査で、どうやらそう簡単に考えてよいものではないらしいことが分かりました。
 以前から_openのハンドル番号とCreateFilのハンドル番号が前者は主に1桁台、後者は2桁台であることに
関心を寄せて来ました。これまでは単に混同しないための配慮かなと思って来たのですが。
(同一ファイルを時間直列でオープン、クローズして実施した際のハンドル番号ですが)

 主な関数群、下記の2系列
_open,_read,_write,_close
CreateFile,ReadFile,WriteFile,CloseHandleについてです。
 
 問題は
VC6++ではファイルアクセスは指定したバイト数でOKであったが
VC++2005以降ファイルアクセスはセクター単位かその整数倍で行われることに変更されたことです。
この変更でディスクアクセスのコーディングが複雑になりました。
今後、ReadFileとWriteFileを使う時は、アタッチメントの役割をする部分を間にはさまなくてはなりません。
それも開発ソフト毎に対応を変える必要があります。
 物理的にディスクアクセスがセクター単位であることは判っていましたから、ファイル設計するときは
なるべくセクター単位と思われる256、512、1024に沿うようにしてきましたが、
そうもできないファイルも多いのが現実です。

 私は当面_openを主に使うことにしますが、皆さんはどうされているのでしょうか。

Re: ReadFileとWriteFile関数について

Posted: 2012年11月14日(水) 15:55
by softya(ソフト屋)
前回のトピックはコレです。名前で検索できるはずですが。
「ディスクアクセスに関して意見をお願いします。 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=11870

少なくともCreateFileはWindows95時代から存在するので極端には変化していないはずです。
なのでVC++6.0の資料は調べられませんが記述漏れがあったとしても変わってはいないはずです。
それと日本語版は誤訳や間違いが結構あるので必ず英語版でも確認して下さい。

と思って見て見たら次の点を読み飛ばしていませんか?
http://msdn.microsoft.com/ja-jp/library/cc429679.aspx
MSDNより引用:
FILE_FLAG_NO_BUFFERING フラグを指定してファイルを開いた後、そのファイルの作業を行う場合、アプリケーションは次の各要件を満たさなければなりません。

•ファイルアクセスは、ボリュームのセクタサイズの整数倍のバイトオフセットの位置で開始しなければなりません。ボリュームのセクタサイズを判断するには、GetDiskFreeSpace 関数を呼び出します。

•ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければなりません。たとえば、セクタサイズが 512 バイトの場合、512 バイト、1,024 バイト、2,048 バイトの読み書きはできますが、335 バイト、981 バイト、7,171 バイトなどの読み書きはできません。

•読み書き操作用のバッファのアドレス(メモリ内のアドレス)を、ボリュームのセクタサイズの整数倍に整列(セクタ整列)させなければなりません。バッファをセクタ整列させる 1 つの方法は、 関数を使ってバッファを割り当てることです。VirtualAlloc 関数が割り当てるメモリは、システムのページサイズの整数倍のアドレスに整列されています。ページサイズとボリュームのセクタサイズは両方とも 2 のべき乗なので、システムのページサイズの整数倍に整列されたメモリは、ボリュームのセクタサイズの整数倍のアドレスにも整列されます。
と言うことで下線部のFILE_FLAG_NO_BUFFERING限定の話だと思います。
日本語版のMSDNサイトの出来が非常に悪いんですけどね。
「ReadFile function (Windows)」 英語版の見やすいこと。
http://msdn.microsoft.com/en-us/library ... s.85).aspx


VC++6.0だろうとVC++2005であろうと最終的に同じCreateFileを呼び出すので動作が違ったら困りますよね。
最初に見た時にVC++2005で作ったアプリがWindows98でも動くのでそんなはずないと思いました。

Re: ReadFileとWriteFile関数について

Posted: 2012年11月14日(水) 17:22
by ISLe
英語版MSDNサイトはわりとさいきんデザインが大幅リニューアルされたのですが、日本語版はそれに追い付いてないんですよね。
特にWin32 APIあたりは(ずっと前から)ひどいですね。
内容の更新が追い付いてないのはもはや当たり前。
重要なキーワードであるリンク部分が欠けている(タグ化け?)とか、一段落すっぽり抜けているとか。


わたしはVC++4のころから、CreateFile使ってますよ。
needsueda さんが書きました: 私は当面_openを主に使うことにしますが、皆さんはどうされているのでしょうか。
前のスレにも書きましたが、ウィンドウズのアプリならCreateFileかfopenの二択ですね。
_openは選択肢にもならないです。


ところで、わたしはCreateFileが返すハンドルの値なんかよりも、needsuedaさんが_openでファイルを作成するときアクセス許可にどういう値を指定しているのかが気になります。

Re: ReadFileとWriteFile関数について

Posted: 2012年11月14日(水) 17:33
by softya(ソフト屋)
そういえばトピックを見失うという問題ならmixc++にユーザー登録してもらうとメールなどで更新メールが届く様に設定できるので見失うことが少なくなるかと思います。
ご検討ください。登録はページの右下にあります。

Re: ReadFileとWriteFile関数について

Posted: 2012年11月14日(水) 18:45
by needsueda
済みません。どうも早とちりのようです。
VC6++のReadFileとWriteFileには注意事項は記載されていませんでしたが、
CreateFileの項目には記載がありました。

Re: ReadFileとWriteFile関数について

Posted: 2012年11月14日(水) 19:19
by softya(ソフト屋)
needsueda さんが書きました:済みません。どうも早とちりのようです。
VC6++のReadFileとWriteFileには注意事項は記載されていませんでしたが、
CreateFileの項目には記載がありました。
どういう意味かわかりませんのでもう少し詳しくお願いします。
それと前回トピックと今回トピックのISLeさんの質問に答えて頂けますでしょうか?

【補足】
出来ればこちらもお願いします。
「scanfについて • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=11838

Re: ReadFileとWriteFile関数について

Posted: 2012年11月15日(木) 20:48
by needsueda
VC6++の中にある解説では
VC6++のReadFileとWriteFileには注意事項は記載されていませんでしたが、
CreateFileの項目には記載がありました。
つまり、VC6++の解説の中のReadFileとWriteFileに記載がないことから
セクタ単位に制限される規制はないと判断したのですが、
ご指摘のCreateFileの解説を読んだところ、先の制限事項の記載があったことから
私の見落としが判りました。そう言う意味で「早とちり」と申し上げたのです。
見落としたのは私の過ちですから。
 VC++2005以降の解説ではCreateFileを含めて全てに制限事項が記載されて
いたため返ってCreateFileも同じだろうと決め付けてしまったことも
「早とちり」をさせられた原因かの知れませんが。

Re: ReadFileとWriteFile関数について

Posted: 2012年11月15日(木) 20:55
by softya(ソフト屋)
えーとCreateFileやReadFileやWriteFileは、FILE_FLAG_NO_BUFFERINGなどを指定しない限り「セクタ単位に制限される規制」はありません。
説明を読んでいるとどんな場合でも制限があると思われている様にしか読み取れてなりません。
どうお考えなのでしょうか?

それと、お願いした「今回トピックのISLeさんの質問に答えて頂けますでしょうか?」は書いて頂けないのでしょうか?