Reputation: 3364
I wrote a simple code snippet to learn the usage of /proc
file system. When I finished, everything is ok except the reading from this file causes an infinite loop.
Some codes show below:
static struct seq_operations proc_seq_ops = {
.start = proc_seq_start,
.next = proc_seq_next,
.stop = proc_seq_stop,
.show = proc_seq_show,
};
int proc_seq_open(struct inode *inode, struct file *filp)
{
return seq_open(filp, &proc_seq_ops);
}
static void *proc_seq_start(struct seq_file *s_file, loff_t *pos)
{
PDEBUG("seq file start\n");
if (list_empty(&store_list_head))
return NULL;
return list_first_entry(&store_list_head, struct store_node, list);
}
static void *proc_seq_next(struct seq_file *s_file, void *v, loff_t *pos)
{
void *tmp = NULL;
PDEBUG("seq file next\n");
tmp = list_next_entry((struct store_node *)v, list);
if (&((struct store_node *)tmp)->list == &store_list_head) {
PDEBUG("seq next return NULL\n");
return NULL;
}
PDEBUG("seq file now is returning %p\n", tmp);
return tmp;
}
static void proc_seq_stop(struct seq_file *s_file, void *v)
{
PDEBUG("seq stop\n");
}
static int proc_seq_show(struct seq_file *s_file, void *v)
{
PDEBUG("%p -> %s\n", v, ((struct store_node *)v)->buf);
seq_printf(s_file, "%p -> %s\n", v, ((struct store_node *)v)->buf);
return 0;
}
The data which will be printed is put in a list. In each invoking of seq_next
, we travel to next node.
The structure of nodes is fairly simple:
struct store_node {
list_head list;
char *buf;
};
When I use cat
command to read this proc file and then check the output by dmesg
, I get this:
[ 893.111027] proc-fs-iterator: seq file next
[ 893.111028] proc-fs-iterator: seq next return NULL
[ 893.111028] proc-fs-iterator: seq stop
[ 893.111036] proc-fs-iterator: seq file start
[ 893.111037] proc-fs-iterator: ffff88002f863dc0 -> 1234
[ 893.111038] proc-fs-iterator: seq file next
[ 893.111039] proc-fs-iterator: seq next return NULL
[ 893.111040] proc-fs-iterator: seq stop
[ 893.111062] proc-fs-iterator: seq file start
[ 893.111064] proc-fs-iterator: ffff88002f863dc0 -> 1234
[ 893.111065] proc-fs-iterator: seq file next
[ 893.111066] proc-fs-iterator: seq next return NULL
[ 893.111067] proc-fs-iterator: seq stop
Why it print infinitely? The seq_stop
is actually executed!
Upvotes: 1
Views: 1634
Reputation: 65870
Your forget to update *pos
parameter in your _next
handler. Usually, it is incremented by 1 every _next
call.
UPDATE: Also your _start
handler should navigate to given position.
Infinite loop is actually a consequence of cat
implementation: it call read(2) until it returns 0 or -1. Because of your implementation do not update position, every read(2) call reads from the beginning and return positive value(non-zero bytes has been read).
BTW, C standard, used in the kernel, allows implicit conversion between void*
and other pointer types. So you can safetly declare tmp
variable in your _next
handler as struct store_node *tmp;
. For example, see seq_list_*
handlers in fs/seq_file.c
kernel source.
Upvotes: 2