UIO(9)

名称
uio, uiomove - デバイスドライバ入出力ルーチン

書式
<sys/types.h> <sys/uio.h>

    struct uio {
    	struct	iovec *uio_iov;
    	int	uio_iovcnt;
    	off_t	uio_offset;
    	int	uio_resid;
    	enum	uio_seg uio_segflg;
    	enum	uio_rw uio_rw;
    	struct	proc *uio_procp;
    };

int uiomove(caddr_t buf, int howmuch, struct uio *uiop)

解説
uiomove() 関数は、ユーザ空間とカーネル空間の境界を越えることさえ可能で、 バッファと入出力ベクタ間のデータ転送の実行に使用されます。

文字型デバイスのドライバに渡された、あらゆる read(2), write(2), readv(2) ないし writev(2) システムコールの結果として、適切なドライバの d_read または d_write エントリが struct uio 構造体のポインタを渡されて呼び出されます。 転送のリクエストは、この構造体の中にエンコードされます。 ドライバ自身もこの構造体の中のデータを取り出すために uiomove() を使用するべきです。

uio 構造体の各フィールドは下記のとおりです。

uio_iov
    処理すべき入出力ベクタの配列です。 散在的な入出力の場合には、一つ以上のベクタとなるでしょう。

uio_iovcnt
    存在している入出力ベクタの数を示します。

uio_offset
    デバイスのオフセットです。

uio_resid
    処理すべきバイト数です。

uio_segflg
    以下のフラグの中の一つです。

    UIO_USERSPACE
        入出力ベクタはプロセスのアドレス空間を指しています。

    UIO_SYSSPACE
        入出力ベクタはカーネルのアドレス空間を指しています。

    UIO_USERISPACE
        入出力ベクタはプロセスのアドレス空間の命令領域を指しています。

    UIO_NOCOPY
        オブジェクト中に既にデータがあり、コピーしません。

uio_rw
    要求された転送の方向を示し、 UIO_READ または UIO_WRITE です。

uio_procp
    スレッドに関連付けられた struct thread 構造体へのポインタです。 uio_segflg がプロセスのアドレス空間との転送をすべきであると示している場合に 使用されます。

使用例
考え方として、ドライバはデータのためのプライベートなバッファの保守を行ない、 このバッファの最大サイズのデータのかたまりの要求を処理します。 下記のバッファの取り扱いはとても簡略化されていて 恐らく動きません(バッファのポインタは部分的な読み込みの場合進みません)し、 uio の取り扱いを実際にやって見せているだけだ、ということに注意してください。

    /* MIN() の定義はこの中にあります */
    #include <sys/param.h>
    #define BUFSIZE 512
    static char buffer[BUFSIZE];
    static int data_available;	/* 読み込めるデータ量 */
    static int
    fooread(dev_t dev, struct uio *uio, int flag)
    {
    	int rv, amnt;
    	while (uio->uio_resid > 0) {
    		if (data_available > 0) {
    			amnt = MIN(uio->uio_resid, data_available);
    			if ((rv = uiomove((caddr_t)buffer, amnt, uio))
    			    != 0)
    				goto error;
    			data_available -= amnt;
    		} else {
    			tsleep(...);	/* より良い時期まで待つ */
    		}
    	}
    	return 0;
    error:
    	/* エラーのクリーンアップをここで行なう */
    	return rv;
    }

戻り値
uiomove() は プロセスのアドレス空間との転送の場合に、 copyin(9) または copyout(9) によって引き起こされた EFAULT を返すことがあります。

関連項目
read(2), readv(2), write(2), writev(2), copyin(9), copyout(9), sleep(9)

歴史
uio の仕組みはある早期のバージョンの UNIX で登場しました。

作者
このマニュアルページは Jörg Wunsch が書きました。