seq_file笔记—3—说明与极简Demo
一、seqfile简介
二、实验
1. 极简Demo
#define pr_fmt(fmt) "seq_test: " fmt#include <linux/kernel.h> #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/seq_file.h>struct student {int id;int start;int last; };static DEFINE_MUTEX(m_lock);static struct student stu[] = {{1, 10, 20},{2, 20, 30},{3, 30, 40},{4, 40, 50},{5, 50, 60}, };static void *get_nth_item(loff_t n) {struct student *s = NULL;if (n >= 0 && n < ARRAY_SIZE(stu)) {s = &stu[n];}pr_info("%s: s=%p, n=%lld\n", __func__, s, n);return s; }static void *demo_start(struct seq_file *m, loff_t *pos) {pr_info("%s: pos=%lld\n", __func__, *pos);mutex_unlock(&m_lock);if (*pos == 0)return SEQ_START_TOKEN;return get_nth_item(*pos - 1); }static void *demo_next(struct seq_file *m, void *v, loff_t *pos) {pr_info("%s: v=%p, pos=%lld\n", __func__, v, *pos);++*pos;return get_nth_item(*pos - 1); }static void demo_stop(struct seq_file *m, void *v) {pr_info("%s: v=%p\n", __func__, v);mutex_unlock(&m_lock); }static int demo_show(struct seq_file *m, void *v) {struct student *item = (struct student *)v;pr_info("%s: v=%p\n", __func__, v);if (v == SEQ_START_TOKEN) {seq_puts(m, "begin dump stu:\n");return 0;}seq_printf(m, "%d %d %d\n", item->id, item->start, item->last);return 0; }static const struct seq_operations demo_seq_ops = {.start = demo_start,.next = demo_next,.stop = demo_stop,.show = demo_show, };static int demo_open(struct inode *inode, struct file *file) {return seq_open(file, &demo_seq_ops); }const struct file_operations proc_demo_operations = {.open = demo_open,.read = seq_read,.llseek = seq_lseek,.release = seq_release, };static int __init seq_demo_init(void) {pr_info("init.\n");proc_create("seq_test", 0666, NULL, &proc_demo_operations);return 0; }module_init(seq_demo_init);
测试日志:
/ # cat /proc/seq_test begin dump stu: 1 10 20 2 20 30 3 30 40 4 40 50 5 50 60
可以看到回调的调用规律:
/ # dmesg -c | grep seq_test: [ 0.722978] (4)[1:swapper/0]seq_test: init. [ 26.979714] (1)[1303:cat]seq_test: demo_start: pos=0 //start 最初传入 pos=0, 返回 v=1 [ 26.986702] (1)[1303:cat]seq_test: demo_show: v=0000000000000001 //show 传入 v=1 [ 26.986946] (2)[1303:cat]seq_test: demo_next: v=0000000000000001, pos=0 //next 传入 v=1 pos=0, 然后将 pos++, 返回首个元素 A。 [ 26.987137] (2)[1303:cat]seq_test: get_nth_item: s=ffffffc01246f1e0, n=0 [ 26.987313] (2)[1303:cat]seq_test: demo_show: v=ffffffc01246f1e0 //show 传入 v=A [ 26.987484] (2)[1303:cat]seq_test: demo_next: v=ffffffc01246f1e0, pos=1 //next 传入 v=A pos=1(上次next中加加了),将 pos++, 返回元素 B。 [ 26.987659] (2)[1303:cat]seq_test: get_nth_item: s=ffffffc01246f1ec, n=1 [ 26.987829] (2)[1303:cat]seq_test: demo_show: v=ffffffc01246f1ec //show 传入 v=B [ 26.988002] (2)[1303:cat]seq_test: demo_next: v=ffffffc01246f1ec, pos=2 //next 传入 v=B pos=2(上次next中加加了),将 pos++, 返回元素 C。 [ 26.988183] (2)[1303:cat]seq_test: get_nth_item: s=ffffffc01246f1f8, n=2 [ 26.988383] (4)[1303:cat]seq_test: demo_show: v=ffffffc01246f1f8 //show 传入 v=C [ 26.988553] (4)[1303:cat]seq_test: demo_next: v=ffffffc01246f1f8, pos=3 //next 传入 v=C pos=3(上次next中加加了),将 pos++, 返回元素 D。 [ 26.988701] (4)[1303:cat]seq_test: get_nth_item: s=ffffffc01246f204, n=3 [ 26.988848] (4)[1303:cat]seq_test: demo_show: v=ffffffc01246f204 //show 传入 v=D [ 26.988985] (4)[1303:cat]seq_test: demo_next: v=ffffffc01246f204, pos=4 //next 传入 v=D pos=4(上次next中加加了),将 pos++, 返回元素 E。 [ 26.989109] (4)[1303:cat]seq_test: get_nth_item: s=ffffffc01246f210, n=4 [ 26.989246] (4)[1303:cat]seq_test: demo_show: v=ffffffc01246f210 //show 传入 v=E [ 26.989372] (4)[1303:cat]seq_test: demo_next: v=ffffffc01246f210, pos=5 //next 传入 v=E pos=5(上次next中加加了),将 pos++, 返回元素 F(NULL) [ 26.989509] (4)[1303:cat]seq_test: get_nth_item: s=0000000000000000, n=5 [ 26.989640] (4)[1303:cat]seq_test: demo_stop: v=0000000000000000 //stop 回调在传入 v=NULL 时触发 [ 26.989813] (4)[1303:cat]seq_test: demo_start: pos=6 //start 再次被调用,传入 pos=6(上次next中加加了), 返回 v=NULL [ 26.989910] (4)[1303:cat]seq_test: get_nth_item: s=0000000000000000, n=5 [ 26.990024] (4)[1303:cat]seq_test: demo_stop: v=0000000000000000 //stop 回调在传入 v=NULL 后再次触发,然后整个过程彻底停止。
基本上是 start --> show --> next --> show --> next --> ... --> stop. 除非主动更新 v 和 pos, 否则在回调传递中保持不变。
可能存在多次 start 和 stop, 但是它两个必定成对出现。
