| UIO(9) | FreeBSD Kernel Developer's Manual | UIO(9) |
名称
uio, uiomove, uiomove_nofault — デバイスドライバ I/O ルーチン書式
#include < sys/types.h>#include < sys/uio.h>
struct uio {
struct iovec *uio_iov; /* scatter/gather リスト */
int uio_iovcnt; /* scatter/gather リストの長さ */
off_t uio_offset; /* タケットオブジェクトの
オフセット */
ssize_t uio_resid; /* コピーする残りのバイト */
enum uio_seg uio_segflg; /* アドレス空間 */
enum uio_rw uio_rw; /* 操作 */
struct thread *uio_td; /* 所有者 */
};
int
uiomove( void *buf, int howmuch, struct uio *uiop);
int
uiomove_nofault( void *buf, int howmuch, struct uio *uiop);
解説
関数 uiomove() と uiomove_nofault() は、場合によりユーザ/カーネル空間の境界に渡るかもしれないバッファと I/O ベクタの間のデータを転送するために使用されます。文字型デバイスのドライバに渡された、あらゆる read(2), write(2), readv(2) または writev(2) システムコールの結果として、適切なドライバの d_read または d_write エントリが struct uio 構造体のポインタを渡されて呼び出されます。転送のリクエストは、この構造体の中にエンコードされます。ドライバ自身もこの構造体の中のデータを取り出すために uiomove() または uiomove_nofault() を使用するべきです。
uio 構造体の各フィールドは、下記のとおりです。
- uio_iov
- 処理すべき入出力ベクタの配列です。散在的な入出力の場合には、一つ以上のベクタとなるでしょう。
- uio_iovcnt
- 存在している入出力ベクタの数を示します。
- uio_offset
- デバイスのオフセットです。
- uio_resid
- 転送の後に更新された処理する残っているバイト数です。
- uio_segflg
-
以下のフラグの中の一つです。
- UIO_USERSPACE
- 入出力ベクタは、プロセスのアドレス空間を指しています。
- UIO_SYSSPACE
- 入出力ベクタは、カーネルのアドレス空間を指しています。
- UIO_NOCOPY
- オブジェクト中に既にデータがあり、コピーしません。
- uio_rw
- 要求された転送の方向を示し、 UIO_READ または UIO_WRITE です。
- uio_td
- スレッドに関連付けられた struct thread 構造体へのポインタです。 uio_segflg がプロセスのアドレス空間との転送をすべきであると示している場合に使用されます。
関数 uiomove_nofault() は、バッファと I/O ベクタがページフォルトせずに、アクセス可能であることを必要とします。発信元と宛先アドレスは、それぞれ読み込みと書き込みアクセスのために物理的にマップされなければなりません、そして、発信元も宛先アドレスもページ可能でないかもしれません。したがって、獲得された仮想記憶システムがロックまたはスリープが禁止されているコンテキストから関数 uiomove_nofault() を呼び出すことができます。
戻り値
成功すれば、 uiomove() と uiomove_nofault() は、0 を返します。エラーのときに、それらは、適切なエラーコードを返します。使用例
考え方として、ドライバは、データのためのプライベートなバッファの保守を行ない、このバッファの最大サイズのデータのかたまりの要求を処理します。下記のバッファの取り扱いはとても簡略化されていて恐らく動きません (バッファのポインタは、部分的な読み込みの場合進みません) し、 uio の取り扱いを実際にやって見せているだけだ、ということに注意してください。
/* MIN() の定義はこの中にあります */
#include <sys/param.h>
#define BUFSIZE 512
static char buffer[BUFSIZE];
static int data_available; /* 読み込めるデータ量 */
static int
fooread(struct cdev *dev, struct uio *uio, int flag)
{
int rv, amnt;
rv = 0;
while (uio->uio_resid > 0) {
if (data_available > 0) {
amnt = MIN(uio->uio_resid, data_available);
rv = uiomove(buffer, amnt, uio);
if (rv != 0)
break;
data_available -= amnt;
} else
tsleep(...); /* より良い時期まで待つ */
}
if (rv != 0) {
/* エラーのクリーンアップをここで行なう */
}
return (rv);
}
エラー
uiomove() と uiomove_nofault() は、失敗すれば、次のエラーコードを返します:- [ EFAULT]
- 呼び出された copyin(9) または copyout(9) が EFAULT を返しました。
さらに、 uiomove_nofault() は、次の場合に失敗して、次のエラーコードを返します:
- [ EFAULT]
- ページフォルトが起こりました。
歴史
uio の仕組みは、ある早期のバージョンの UNIX で登場しました。作者
このマニュアルページは、 によって書かれました。| January 19, 2012 | FreeBSD |