EN JA
MAKE_DEV(9)
MAKE_DEV(9) FreeBSD Kernel Developer's Manual MAKE_DEV(9)

名称

make_dev, make_dev_cred, make_dev_credf, make_dev_p, make_dev_alias, make_dev_alias_p, destroy_dev, destroy_dev_sched, destroy_dev_sched_cb, destroy_dev_drain, dev_dependsデバイスのための cdev と DEVFS 登録を管理する

書式

#include < sys/param.h>
#include < sys/conf.h>

struct cdev *
make_dev( struct cdevsw *cdevsw, int unit, uid_t uid, gid_t gid, int perms, const char *fmt, ...);

struct cdev *
make_dev_cred( struct cdevsw *cdevsw, int unit, struct ucred *cr, uid_t uid, gid_t gid, int perms, const char *fmt, ...);

struct cdev *
make_dev_credf( int flags, struct cdevsw *cdevsw, int unit, struct ucred *cr, uid_t uid, gid_t gid, int perms, const char *fmt, ...);

int
make_dev_p( int flags, struct cdev **cdev, struct cdevsw *devsw, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, ...);

struct cdev *
make_dev_alias( struct cdev *pdev, const char *fmt, ...);

int
make_dev_alias_p( int flags, struct cdev **cdev, struct cdev *pdev, const char *fmt, ...);

void
destroy_dev( struct cdev *dev);

void
destroy_dev_sched( struct cdev *dev);

void
destroy_dev_sched_cb( struct cdev *dev, void (*cb)(void *), void *arg);

void
destroy_dev_drain( struct cdevsw *csw);

void
dev_depends( struct cdev *pdev, struct cdev *cdev);

解説

make_dev_credf() 関数は、新しいデバイスのための cdev 構造体を作成します。また、それは新しいデバイスの存在を devfs(5) に通知して、対応するノードを作成します。これに加えて、 devctl(4) 通知が送信されます。デバイスは、 gid のグループ所有権をつけて uid によって所有されます。名前は、 fmt と拡張と printf(9) がそれを印刷する次の引数です。名前は、 /dev または、他の devfs(5) マウントポイント下のパスを決定して、サブディレクトリを指示するスラッシュ‘ /’文字を含みます。 perms で指定されるファイルのパーミッションは、 < sys/stat.h> に定義されています。

#define S_IRWXU 0000700    /* 所有者のための RWX マスク 
#define S_IRUSR 0000400    /* 所有者のための R */ 
#define S_IWUSR 0000200    /* 所有者のための W */ 
#define S_IXUSR 0000100    /* 所有者のための X */ 
 
#define S_IRWXG 0000070    /* グループのための RWX マスク */ 
#define S_IRGRP 0000040    /* グループのための R */ 
#define S_IWGRP 0000020    /* グループのための W */ 
#define S_IXGRP 0000010    /* グループのための X */ 
 
#define S_IRWXO 0000007    /* その他のための RWX マスク */ 
#define S_IROTH 0000004    /* その他のための R */ 
#define S_IWOTH 0000002    /* その他のための W */ 
#define S_IXOTH 0000001    /* その他のための X */ 
 
#define S_ISUID 0004000    /* 実行時のセットユーザ ID */ 
#define S_ISGID 0002000    /* 実行時のセットグループ ID */ 
#define S_ISVTX 0001000    /* スティッキビット */ 
#ifndef _POSIX_SOURCE 
#define S_ISTXT 0001000 
#endif

cr 引数は、初期化している struct cdevsi_cred メンバに格納される資格証明を指定します。 flags 引数は、 make_dev_credf() または make_dev_p() の動作を変更します。現在、次の値が受け付けられます:

MAKEDEV_REF
作成されたデバイスを参照
MAKEDEV_NOWAIT
sleep しません、呼び出しは、失敗します
MAKEDEV_WAITOK
malloc を満たすために関数は、sleep することができます
MAKEDEV_ETERNAL
作成されたデバイスは、決して破壊されません
MAKEDEV_CHECKNAME
デバイス名が不正であるか、または既に存在するなら、エラーを返します

MAKEDEV_NOWAIT, MAKEDEV_WAITOKMAKEDEV_CHECKNAME 値だけが、 make_dev_alias_p() 関数のために受け付けられます。

MAKEDEV_WAITOK, MAKEDEV_NOWAIT のいずれも指定されなければ、 MAKEDEV_WAITOK フラグが仮定されます。

devfs_lookup(9) が cdev への参照を落す直後に破壊されるところで競合を避けるために、作成されたデバイスが、検索のために応答でデバイスを作成するとき、 dev_clone(9) イベントハンドラは、 MAKEDEV_REF フラグを指定するものとします。

MAKEDEV_ETERNAL フラグによって、カーネルは、システムコールを cdevsw メソッド呼び出しに変換するとき、いくつかのロックを獲得できません。 destroy_dev() が返された cdev で決して呼び出されないことを保証するのは、ドライバの作者の責任です。利便性のために、カーネルにコンパイルするか、またはローダブルモジュールとしてロード (アンロード) することができるコードに対して MAKEDEV_ETERNAL_KLD フラグを使用します。

MAKEDEV_CHECKNAME フラグが指定されず、デバイス名が不正であるか、または既に存在しているなら、パニックが起こります。

make_dev_cred() 関数は、次の呼び出しと同等です。

make_dev_credf(0, cdevsw, unit, cr, uid, gid, perms, fmt, ...);

make_dev() 関数呼び出しは、次と同じです。

make_dev_credf(0, cdevsw, unit, NULL, uid, gid, perms, fmt, ...);

make_dev_p() 関数は、 make_dev_credf() と同様ですが、エラー番号を返し、引数として結果の *cdev へのポインタを取ります。

make_dev_alias() 関数は、 make_dev() から返された cdev を取り、このデバイスのために別の (エイリアスされる) 名前を作成します。 make_dev() を呼び出す前に make_dev_alias() を呼び出しは、エラーです。

make_dev_alias_p() 関数は、 make_dev_alias() と同様ですが、引数として結果の *cdev へのポインタを取り、エラーを返します。

make_dev() と make_dev_alias() によって返された cdev には、状態を格納するために利用可能な、2 つのフィールド si_drv1si_drv2 があります。両方のフィールドは、タイプ void * です。これらは、 unit 引数を、 dev2unit() で取得できる、 make_dev() に置き換えるようにを設計されています。

destroy_dev() 関数は、 make_dev() から返された cdev を取り、そのデバイスのための登録を破壊します。破壊イベントに関する通知が、 devctl(4) に送られます。 make_dev_alias() で作成されたデバイスで destroy_dev() を呼び出さないでください。

dev_depends() 関数は、2 つのデバイスの間の親子関係を確立します。ネットの影響は、親デバイスの destroy_dev() が、存在しているなら、(複数の) 子供のデバイスも破壊する結果となります。デバイスは、同時に親と子供であるかもしれないので、完全な階層構造を構築することは可能です。

destroy_dev_sched_cb() 関数は、安全なコンテキストで指定された cdev のために destroy_dev() の実行をスケジュールします。 destroy_dev() が終了した後に、供給された cbNULL でないなら、コールバック cb が、引数 arg で呼び出されます。 destroy_dev_sched() 関数は、次と同じです。

destroy_dev_sched_cb(cdev, NULL, NULL);

d_close() ドライバの方法は、直接 destroy_dev() を呼び出すことができません。そうすることは、 destroy_dev() が、ドライバの方法に任せるすべてのスレッドを待つとき、デッドロックを引き起こします。また、 destroy_dev() は、スリープするので、スリープ不可能なロックは、呼び出しにわたって保持されません。 destroy_dev_sched() 関数ファミリは、これらの問題を克服します。

デバイスドライバは、cdevsw として供給された csw があるすべてのデバイスが破壊されるまで、待つために、 destroy_dev_drain() 関数を呼び出します。ドライバは、 destroy_dev_sched() がすべての例示されたデバイスを呼び出すことを知っていますが、 destroy_dev() が実際にそれらのすべてが終了するまで、モジュールのアンロードを延期するのが必要があるとき、役に立ちます。

戻り値

成功するなら、 make_dev_p() は、0 を返し、そうでければ、エラーを返します。成功するなら、 make_dev_credf() は、有効な cdev ポインタを返し、そうでければ、 NULL を返します。

エラー

make_dev_p() と make_dev_alias_p() 呼び出しは、次の場合に失敗して、デバイスは、登録されません:
[ ENOMEM]
MAKEDEV_NOWAIT フラグが指定され、メモリ割り付け要求を満たすことができませんでした。
[ ENAMETOOLONG]
MAKEDEV_CHECKNAME フラグが指定され、提供されたデバイス名が、 SPECNAMELEN より長いです。
[ EINVAL]
MAKEDEV_CHECKNAME フラグが指定され、提供されたデバイス名が空であり、“.”または“..”パス構成要素を含むか、または‘ /’で終っています。
[ EINVAL]
MAKEDEV_CHECKNAME フラグが指定され、提供されたデバイス名が不正な文字を含んでいます。
[ EEXIST]
MAKEDEV_CHECKNAME フラグが指定され、提供されたデバイス名が既に存在しています。

歴史

make_dev() と destroy_dev() 関数は、 FreeBSD 4.0 ではじめて登場しました。関数 make_dev_alias() は、 FreeBSD 4.1 ではじめて登場しました。関数 dev_depends() は、 FreeBSD 5.0 ではじめて登場しました。関数 make_dev_credf(), destroy_dev_sched(), destroy_dev_sched_cb() は、 FreeBSD 7.0 ではじめて登場しました。関数 make_dev_p() は、 FreeBSD 8.2 ではじめて登場しました。
December 22, 2012 FreeBSD