Ftraceは、debugfsファイルを操作することによって制御されます。しかし、それはどのように可能ですか?カーネルはこのファイルへの書き込みをどのように認識し、必要なアクションを開始しますか?たとえば、traceing_onに1が書き込まれると、カーネルはトレースをオンにします。それは特別なファイル構造に関連するものですか、それともカーネルがdebugfsの変更をサブスクライブするのですか、それとも明らかなものがありませんか?
私はそれを見つけたと思います。これによると link カーネルでは、文字タイプのデバイスは、システムに登録するために使用される構造体であるstructcdevで表されます。ほとんどのドライバー操作は、struct file_operations、struct file、およびstructinodeの3つの重要な構造体を使用します。上記のように、キャラクターデバイスドライバーは、デバイスタイプのファイルを介してユーザーが行った変更されていないシステムコールを受信します。したがって、文字デバイスドライバーの実装とは、ファイルに固有のシステムコール(open、close、read、write、lseek、mmapなど)を実装することを意味します。これらの操作は、structfile_operations構造体のフィールドで説明されています。
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 *);
[...]
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
[...]
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
[...]
したがって、上記の関数ポインタを目的の関数で初期化できます。たとえば、traceing_onの場合、これはkernel/trace/trace.cでの初期化であり、関数は同じファイルに実装されています。
static const struct file_operations rb_simple_fops = {
.open = tracing_open_generic_tr,
.read = rb_simple_read,
.write = rb_simple_write,
.release = tracing_release_generic_tr,
.llseek = default_llseek,
};
また、これはこのディレクトリを作成するためのコードです。
trace_create_file("tracing_on", 0644, d_tracer,
tr, &rb_simple_fops);