/* * procfs4.c - 创建一个使用seq_file库来管理的/proc文件 */ #include #include #include #include /* 引入 seq_file */ #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) #define HAVE_PROC_OPS #endif #define PROC_NAME "iter" /* 这个函数在序列开始时被调用, 即: * - 第一次读取 /proc 文件时 * - 或在调用 stop 函数后(序列结束时) */ static void *my_seq_start(struct seq_file *s, loff_t *pos) { static unsigned long counter = 0; /* 是否开始一个新的序列? */ if (*pos == 0) { /* yes => 返回非 NULL 值以开始序列 */ return &counter; } /* no => 这是序列的结束,返回 NULL 以停止读取 */ *pos = 0; return NULL; } /* 这个函数在序列开始后被调用。它会被调用直到返回 NULL(序列结束) */ static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos) { unsigned long *tmp_v = (unsigned long *)v; (*tmp_v)++; (*pos)++; return NULL; } /* 这个函数在序列结束时被调用 */ static void my_seq_stop(struct seq_file *s, void *v) { /* 无需操作,因为我们在 start() 中使用了静态值 */ } /* 这个函数在序列的每一步中被调用 */ static int my_seq_show(struct seq_file *s, void *v) { loff_t *spos = (loff_t *)v; seq_printf(s, "%Ld\n", *spos); return 0; } /* 这个结构体包含了管理序列的函数 */ static struct seq_operations my_seq_ops = { .start = my_seq_start, .next = my_seq_next, .stop = my_seq_stop, .show = my_seq_show, }; /* 这个函数在打开 /proc 文件时被调用 */ static int my_open(struct inode *inode, struct file *file) { return seq_open(file, &my_seq_ops); }; /* 这个结构体包含了管理 /proc 文件的函数 */ #ifdef HAVE_PROC_OPS static const struct proc_ops my_file_ops = { .proc_open = my_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = seq_release, }; #else static const struct file_operations my_file_ops = { .open = my_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; #endif static int __init procfs4_init(void) { struct proc_dir_entry *entry; entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops); if (entry == NULL) { pr_debug("错误:无法初始化 /proc/%s\n", PROC_NAME); return -ENOMEM; } return 0; } static void __exit procfs4_exit(void) { remove_proc_entry(PROC_NAME, NULL); pr_debug("/proc/%s 已移除\n", PROC_NAME); } module_init(procfs4_init); module_exit(procfs4_exit); MODULE_LICENSE("GPL");