当前位置: 首页 > news >正文

seq_file笔记—3—说明与极简Demo - Hello

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, 但是它两个必定成对出现。