我在proc下创建了一个文件来读取字符串,但是我没有使用seq_file实现,而是可以使用file_operations中的ssize_t(* read)方法读取它。这种方法有误吗?
有谁能解释一下我在使用seq_file实现的哪些情况下更好?
ssize_t my_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *offset)
{
printk(KERN_INFO "loff_t *offset = %lld\n", *offset);
printk(KERN_INFO "count = %lu\n", count);
/* comment below two lines and check what happens. If we don't return
0 it means there is still some data and read is called repeatedly. */
if((int)*offset >= ARRAY_LEN)
return 0;
*offset += ARRAY_LEN;
return sprintf(buffer, "%s\n", param);
}
同样在输出中我总是算数是131072,为什么会这样?
[ 7317.855146] loff_t *offset = 131073
[ 7317.855149] count = 131072
答案 0 :(得分:1)
seq_file
对于文件很有用,内容不会存储在某个地方,但是当用户需要时,动态生成。它可以使用单个格式字符串生成(如问题帖子中的%s\n
),也可以组合不同或相同类型的块。
使用seq_file
功能时,代码编写器不会为要读入的缓冲区大小,当前文件的偏移量以及使用__user
访问copy_to_user()
数据而烦恼。相反,他专注于生成文件的内容,就好像它是一些无限大小的流。其他所有内容都由seq_file
机制自动处理。
例如,给出的例子可以使用seq_file
实现,如下所示:
int param_show(struct seq_file *m, void *v)
{
(void)v; /* Unused */
seq_printf(m, "%s\n", param); /* Just generate content of the "file" */
return 0;
}
int my_proc_open(struct inode *inode, struct file *filp)
{
return single_open(filp, ¶m_show, NULL);
}
const struct file_operations my_proc_ops = {
.owner = THIS_MODULE,
.open = &my_proc_open,
.read = &seq_read
};
为了进行比较,直接实现了相同的读取功能:
ssize_t my_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *offset)
{
ssize_t ret;
size_t param_len = strlen(param);
/* Write to buffer everything except terminating '\n' */
ret = simple_read_from_buffer(buffer, count, offset, param, param_len);
/* But processing of additional '\n' is much more complex */
if (ret >= 0 && ret < (ssize_t)count && *offset == param_len) {
char ch = '\n';
int err = put_user(buffer + ret, &ch); /* Try to append '\n' */
if (!err) {
/* Success */
++ret;
++(*offset);
} else if (!ret) {
/* Fail and nothing has been read before */
ret = err;
}
}
return ret;
}
const struct file_operations my_proc_ops = {
.owner = THIS_MODULE,
.read = &my_proc_read
};
正如我们所看到的,虽然阅读params
的预备内容是单行(使用帮助simple_read_from_buffer
),但应该生成的其他\n
,使实施更加困难。
seq_file
的缺点在于其性能:.show
函数中生成的内容未缓存,因此每个后续的read()
系统调用都需要再次调用.show
。此外,为了生成文件的内容,使用内部缓冲区,并且应该在堆中分配此缓冲区。
但在大多数情况下,动态生成的文件很少和/或很少读取和/或性能不高。所以seq_file
适用于几乎所有情况下的此类文件。