当我从使用 seq_file 实现的 /proc 读取时无限循环

Infinite loop when I read from /proc which is implemented with seq_file

我写了一个简单的代码片段来学习 /proc 文件系统的用法。当我完成后,一切正常,除了读取这个文件导致无限循环。

部分代码如下:

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;
}

要打印的数据放在一个列表中。在每次调用 seq_next 时,我们都会前往下一个节点。

节点的结构相当简单:

struct store_node {
    list_head list;
    char *buf;
};

当我使用 cat 命令读取此 proc 文件然后通过 dmesg 检查输出时,我得到:

[  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

为什么会无限打印? seq_stop实际执行!

您忘记更新 _next 处理程序中的 *pos 参数。通常,它在每 _next 次调用时递增 1。 更新:您的 _start 处理程序也应导航到给定位置。

无限循环实际上是 cat 实现的结果:它调用 read(2) 直到它 returns 0 或 -1。由于您的实现不更新位置,每个 read(2) 调用从头开始读取 return 正值(已读取非零字节)。

BTW,内核中使用的C标准,允许void*和其他指针类型之间的隐式转换。因此,您可以在 _next 处理程序中安全地将 tmp 变量声明为 struct store_node *tmp;。例如,请参阅 fs/seq_file.c 内核源代码中的 seq_list_* 处理程序。