[[PageNavi(internal22-navi)]]
{{{ comment
h2w-title:ファイルへの書き込みとファイル拡張
}}}
= ファイルへの書き込みとファイル拡張 = #SECTION031060000000000000000
writeシステムコールは、vfs sys_write関数にて、ファイルディスクリプタに対応するファイル構造体を見つけ(fget関数)、ファイル構造体に登録されているwriteオペレーションを呼び出す。
ext2ファイルシステムの場合、 通常ファイルではext2_file_write関数が呼び出される。ディレクトリ、シンボリックリンクファイルの場合、このオペレーションは無登録であるため、sys_write処理はエラー終了する。
{{{
ext2_file_write(ファイル構造体、ユーザ領域, ファイルポインタ)
if(アペンドモードなら) ファイルポインタをファイルエンドにする
do {
ファイルブロックに対応したバッファ確保(ext2_getblk関数)
- ブロックが割り当てられてなければ、自動的に割り当てられる
if(I/Oサイズがブロックサイズでなく && バッファの中身が無効) {
ブロックをバッファへ読み込む(ll_rw_block関数, wait_on_buffer関数)
}
ユーザ領域のデータをバッファに読み込む(copy_from_user関数)
ページキャッシュにも書き込み内容を反映(update_vm_cache関数)
バッファを有効状態にする(mark_buffer_uptodate関数)
◇バッファの遅延書き込み要求(mark_buffer_dirty関数)
if(O_SYNCモードのオープンのとき) {
if(ある程度バッファが溜まったら) {
◆バッファを同期書き込み(ll_rw_block関数、wait_on_buffer関数)
バッファを解放
}
} else {
バッファを解放
}
} while(書き込むデータがある間)
if(O\_SYNCモードのオープンのとき) {
if(まだ書き込みをしていないバッファにたいして)
◆バッファを同期書き込み(ll_rw_block関数、wait_on_buffer関数)
バッファを解放
}
}
if(ファイル拡張が発生していたら)
ファイルサイズを変更する(iノードのi_sizeメンバ)
ファイルポインタを進める
◇iノードの遅延書き込み要求(mark_inode_dirty関数)
}}}
ネットワークファイルシステムのwriteオペレーションは、generic_file_write関数により、ページキャッシュ経由の書き込みとして実現されるが、それ以外のローカルディスク上のそれぞれが独自のwriteオペレーションを持ち、バッファキャッシュ経由で書き込みが行われる。
'''問題点'''
1. ファイル拡張は、ext2_getblk関数の中で自動的に行われる。 ファイル拡張時の問題点は、ext2_getblk関数を参照のこと。
1. O_SYNCでopenしているファイルにおいてファイル拡張が発生しても、 ファイルのiノードが遅延書き込みとなっているため、ファイルサイズの 更新が遅れている。ファイル構造的には問題はないが、ユーザが期待している ものとは異なった動作となる。
----
''(NIS)HirokazuTakahashi [[BR]]2000年06月11日 (日) 22時29分57秒 JST''1
[[PageNavi(internal22-navi)]]