Ftrace는 디버그 fs 파일을 작동하여 제어됩니다. 그런데 이것이 어떻게 가능합니까? 커널은 이 파일의 쓰기를 어떻게 알고 필요한 작업을 시작합니까? 예를 들어, tracing_on에 1을 쓰면 커널이 추적을 켭니다. 특별한 파일 구조나 debugfs에 대한 커널 구독 변경과 관련이 있습니까? 아니면 분명한 것이 빠졌습니까?
답변1
찾은 것 같아요. 이에 따르면협회 커널에서 문자 유형 장치는 시스템에 등록하는 데 사용되는 struct cdev로 표시됩니다. 대부분의 드라이버 작업은 구조체 파일 작업, 구조체 파일 및 구조체 inode라는 세 가지 중요한 구조를 사용합니다. 위에서 언급한 것처럼 캐릭터 장치 드라이버는 장치 유형 파일을 통해 사용자가 발행한 변경되지 않은 시스템 호출을 받습니다. 따라서 문자 장치 드라이버의 구현은 파일별 시스템 호출(열기, 닫기, 읽기, 쓰기, lseek, mmap 등)을 구현하는 것을 의미합니다. 이러한 작업은 struct file_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 *);
[...]
따라서 우리가 원하는 함수로 위의 함수 포인터를 초기화할 수 있습니다. 예를 들어 tracing_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);