main {}
デバイスドライバーは、開始点と終了点を持つ「プログラム」ではありません。API、ライブラリ、またはルーチンのコレクションに似ています。この場合、それは, , おそらくおよび操作のエントリ ポイントをリストする構造体によって宣言されたエントリ ポイントのセットです。MODULE_INIT()
MODULE_EXIT()
EXPORT_SYMBOL()
ブロック デバイスの場合、ドライバーは、(からinclude/linux/blkdev.h
)でそれらの操作の関数を宣言することにより、実行できる操作のリストを提供することが期待されます。
struct block_device_operations {
int (*open) ();
int (*release) ();
int (*ioctl) ();
int (*compat_ioctl) ();
int (*direct_access) ();
unsigned int (*check_events) ();
/* ->media_changed() is DEPRECATED, use ->check_events() instead */
int (*media_changed) ();
void (*unlock_native_capacity) ();
int (*revalidate_disk) ();
int (*getgeo)();
/* this callback is with swap_lock and sometimes page table lock held */
void (*swap_slot_free_notify) ();
struct module *owner;
};
char デバイスの場合、ドライバーは、(from からinclude/linux/fs.h
)でそれらの操作の関数を宣言することにより、実行できる操作のリストを提供することが期待されます。
struct file_operations {
struct module *owner;
loff_t (*llseek) ();
ssize_t (*read) ();
ssize_t (*write) ();
ssize_t (*aio_read) ();
ssize_t (*aio_write) ();
int (*readdir) ();
unsigned int (*poll) ();
long (*unlocked_ioctl) ();
long (*compat_ioctl) ();
int (*mmap) ();
int (*open) ();
int (*flush) ();
int (*release) ();
int (*fsync) ();
int (*aio_fsync) ();
int (*fasync) ();
int (*lock) ();
ssize_t (*sendpage) ();
unsigned long (*get_unmapped_area)();
int (*check_flags)();
int (*flock) ();
ssize_t (*splice_write)();
ssize_t (*splice_read)();
int (*setlease)();
long (*fallocate)();
};
プラットフォーム デバイスの場合、ドライバーは、実行できる操作のリストを提供することが期待されます。これらの操作の関数を (からinclude/linux/platform_device.h
) で宣言します。
struct platform_driver {
int (*probe)();
int (*remove)();
void (*shutdown)();
int (*suspend)();
int (*resume)();
struct device_driver driver;
const struct platform_device_id *id_table;
};
ドライバー、特に char ドライバーは、リストされているすべての操作をサポートする必要はありません。構造エントリに名前を付けることで、これらの構造のコーディングを容易にするマクロがあることに注意してください。
ドライバ プログラムは MOUDLUE_INIT() マクロで開始しますか?
で指定されたドライバのinit()ルーチンは、MODULE_INIT()
起動中 (静的にリンクされている場合) またはモジュールが動的にロードされている場合に呼び出されます。ドライバーは、 init()中に自身を登録するときに、操作の構造をデバイスのサブシステムに渡します。
これらのデバイス ドライバー エントリ ポイント( open()やread()など) は通常、ユーザー アプリが (ユーザー空間で) C ライブラリ呼び出しを呼び出したとき、およびカーネル空間への切り替え後に実行されます。あなたが見ている i2c ドライバーは、リーフデバイスによって使用されるバスのプラットフォーム ドライバーであり、によって公開されるその関数は、他のドライバーによって呼び出されることに注意してください。EXPORT_SYMBOL()
で指定されたドライバのinit()ルーチンのみMODULE_INIT()
が呼び出されることが保証されています。で指定されたドライバのexit()ルーチンMODULE_EXIT()
は、モジュールが動的にアンロードされた場合にのみ実行されます。ドライバの op ルーチンは、未知の順序で (割り込みサービス ルーチンと同様に) 非同期的に呼び出されます。ユーザー プログラムがread()またはioctl()操作を発行する前にopen()を呼び出し、適切な方法で他の操作を呼び出すことを願っています。適切に作成された堅牢なドライバーは、操作の順序やシーケンスに対応し、適切な結果を生成してシステムの整合性を確保する必要があります。