tail head cat sleep
QR code linking to this page

manページ  — VOP_RDWR

名称

VOP_READ, VOP_WRITE – ファイルの読み込みまたは書き込み

内容

書式

#include <sys/param.h>
#include <sys/vnode.h>
#include <sys/uio.h>

int
VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred);

int
VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred);

解説

これらのエントリポイントは、ファイルの内容を読み込みまたは書き込みます。

引数は以下の通りです。
vp
  ファイルの vnode。
uio
  読み込みまたは書き込み対象のデータの位置。
ioflag
  様々なフラグ。
cnp
  呼び出し側の証明。

ioflag 引数は、ファイルシステムに対する命令およびヒントを与えるために使用されます。 読み込みを試みる時には、上位の 16 ビットは、 ファイルシステムが試みるべき先読みのヒントを (ファイルシステムブロック単位で) 提供するために使用されます。 下位の 16 ビットは、以下のフラグを含むことができるビットマスクです。
IO_UNIT 不可分に入出力を行ないます。
IO_APPEND 末尾に追加書き込みを行ないます。
IO_SYNC 同期的に入出力を行ないます。
IO_NODELOCKED
  下位層のノードは既にロックされています。
IO_NDELAY ファイルテーブルに FNDELAY フラグを設定します。
IO_VMIO 仮想メモリ入出力 (VMIO) 領域にデータが既にあります。

ロック

入る時に、ファイルはロックされているべきで、終了時までロックされ続けます。

戻り値

成功時には 0 が返され、そうでない場合にはエラーコードが返されます。

疑似コード

int
vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
{
    struct buf *bp;
    off_t bytesinfile;
    daddr_t lbn, nextlbn;
    long size, xfersize, blkoffset;
    int error;

size = block size of file system;

for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {         bytesinfile = size of file - uio->uio_offset;         if (bytesinfile <= 0)          break;

        lbn = uio->uio_offset / size;         blkoffset = uio->uio_offset - lbn * size;

        xfersize = size - blkoffset;         if (uio->uio_resid < xfersize)          xfersize = uio->uio_resid;         if (bytesinfile < xfersize)          xfersize = bytesinfile;                  error = bread(vp, lbn, size, NOCRED, &bp);         if (error) {          brelse(bp);          bp = NULL;          break;         }

        /*          * 入出力エラーが起こった時には 0 でない b_resid のみ          * を得ます。これは上で break を引き起こすべきです。          * しかしながら、短い読み込みがエラーを起こさなかった          * 場合には、間違ったまたは初期化されていないデータの          * uiomove を行なわないことを保証したい。          */         size -= bp->b_resid;         if (size < xfersize) {          if (size == 0)                 break;          xfersize = size;         }                  error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);         if (error)          break;

        bqrelse(bp); } if (bp != NULL)         bqrelse(bp);

return (error); }

int vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct buf *bp; off_t bytesinfile; daddr_t lbn, nextlbn; off_t osize; long size, resid, xfersize, blkoffset; int flags; int error;

osize = size of file; size = block size of file system; resid = uio->uio_resid; if (ioflag & IO_SYNC)         flags = B_SYNC; else         flags = 0;

for (error = 0; uio->uio_resid > 0;) {         lbn = uio->uio_offset / size;         blkoffset = uio->uio_offset - lbn * size;

        xfersize = size - blkoffset;         if (uio->uio_resid < xfersize)          xfersize = uio->uio_resid;                  if (uio->uio_offset + xfersize > size of file)          vnode_pager_setsize(vp, uio->uio_offset + xfersize);

        if (size > xfersize)          flags |= B_CLRBUF;         else          flags &= ~B_CLRBUF;

        error = find_block_in_file(vp, lbn, blkoffset + xfersize,                                  cred, &bp, flags);         if (error)          break;

        if (uio->uio_offset + xfersize > size of file)          set size of file to uio->uio_offset + xfersize;

        error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);         /* XXX ufs はここでエラーチェックをしていません。何故? */

        if (ioflag & IO_VMIO)          bp->b_flags |= B_RELBUF; /* ??? */

        if (ioflag & IO_SYNC)          bwrite(bp);         else if (xfersize + blkoffset == size)          bawrite(bp);         else          bdwrite(bp);

        if (error || xfersize == 0)          break; }

if (error) {         if (ioflag & IO_UNIT) {          /* ファイルを切り詰める私的なルーチンを呼び出す。 */          your_truncate(vp, osize, ioflag & IO_SYNC, cred, uio->uio_td);          uio->uio_offset -= resid - uio->uio_resid;          uio->uio_resid = resid;         } } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {         struct timeval tv;         error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX これは何をしているの? */ }

return (error); }

エラー

[EFBIG]
  プロセスのファイルサイズリミットまたは最大ファイルサイズを超える ファイルを書込もうとしました。
[ENOSPC]
  ファイルシステムが一杯です。
[EPERM]
  追加のみのフラグがファイルに設定されていますが、呼び出し側が現在の ファイル終了位置より前に書込もうとしました。

関連項目

uiomove(9), vnode(9)

作者

このマニュアルページは Doug Rabson が書きました。

VOP_RDWR (9) July 24, 1996

tail head cat sleep
QR code linking to this page


このマニュアルページサービスについてのご意見は Ben Bullock にお知らせください。 Privacy policy.