このドキュメントで説明するソフトウェアは、Extended SupportまたはSustaining Supportのいずれかにあります。 詳細は、https://www.oracle.com/us/support/library/enterprise-linux-support-policies-069172.pdfを参照してください。
Oracleでは、このドキュメントに記載されているソフトウェアをできるだけ早くアップグレードすることをお薦めします。

機械翻訳について

6.5 文字デバイス・ドライバについて

文字デバイス・ドライバがサポートするデバイスは、固定長ではなく可変長データを処理し、物理的にアドレス可能なストレージ・メディアにはアクセスしません(またはファイル・システム・アクセスをサポートしません)。 文字デバイス・ドライバを使用するデバイスの例としては、キーボード、マウス、ビデオ・カードなどがあります(ただし、USB形式のキーボードやマウスではUSBデバイス・ドライバが必要です)。

大半の文字デバイス・ドライバの実装は、LinuxとUNIXオペレーティング・システムで非常によく似ていますが、相違点のほとんどはドライバのファイル操作の定義に使用する構造体に関するものです。

<linux/fs.h>に定義された文字デバイスのfile_operations構造体には一連のメソッド・ポインタが含まれ、それによりシステムがopen()read()write()ioctl()などのシステム・コールを使用するときに、/devの下にあるデバイス・ファイル経由でデバイスとやり取りする方法が指定されます。

struct file_operations {
        struct module *owner;
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
        ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        ssize_t (*read_iter) (struct kiocb *, struct iov_iter *, loff_t);
        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        ssize_t (*write_iter) (struct kiocb *, struct iov_iter *, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *, fl_owner_t id);
        int (*release) (struct inode *, struct file *);
        int (*fsync) (struct file *, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
        ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long,
                       unsigned long, unsigned long);
        int (*check_flags)(int);
        int (*flock) (struct file *, int, struct file_lock *);
        ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
                                size_t, unsigned int);
        ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
                               size_t, unsigned int);
        int (*setlease)(struct file *, long, struct file_lock **);
        long (*fallocate)(struct file *file, int mode, loff_t offset,
                          loff_t len);
};

単純な文字デバイス・ドライバであれば、次のように、この構造体に定義された関数のサブセットを実装するだけで作成できる場合があります。

struct file_operations driver_fileops = {
    .owner   = THIS_MODULE,
    .llseek  = driver_llseek,
    .read    = driver_read,
    .write   = driver_write,
    .ioctl   = driver_ioctl,
    .open    = driver_open,
    .release = driver_release,
};

これらのメソッドの他に、ドライバのロード/アンロード時にコールされるドライバ用のmodule_init()初期化ルーチンとmodule_exit()クリーンアップ・ルーチンを定義するのが一般的です。 これらのルーチンはregister_chrdev()およびunregister_chrdev()をコールして、ドライバのデバイス・メジャー番号を登録/登録解除します。

ほとんどの文字デバイス・ドライバでは、割込みハンドラを宣言してデバイスからの着信データを非同期に受け入れます。 ドライバを初期化する場合、request_irq()を使用して割込みハンドラをインストールしますが、その際、flags引数のSA_SHIRQビットと、一意のdev_id(ハンドラはこれを使用して、処理する必要のある割込みを特定できます)を設定して、共有割込みを必ず指定してください。 クリーンアップではfree_irq()をコールしてハンドラを登録解除します。 ドライバがポーリングを使用して着信データをチェックすることもできますが、これは一般的ではありません。

<linux/fs.h>に定義された文字デバイスのfile構造体では、デバイスのオープン時にカーネルが作成するカーネル空間のデータ構造体を指定します。

file構造体の最も重要なメンバーを次に示します。

f_flags

デバイス操作の動作方法(非ブロック読取りなど)を指定するファイル制御フラグ。

f_mode

ファイルの読取りと書込みが可能かどうかを示すモード。

f_op

ファイル関連の操作(通常はデバイス・マイナー番号によって異なります)。

f_pos

ファイル内の現在の読取り/書込みオフセット。

private_data

デバイスが解放されるまでシステム・コール間でデバイスに関するデータを保持できます。

デバイスのinodeのメジャー番号とマイナー番号を取得するには、次のマクロを使用しますが、これも<linux/fs.h>に定義されています。

unsigned iminor(struct inode *inode);
unsigned imajor( struct inode *inode);