gpt4 book ai didi

c - scull 的 proc read 实现中的参数是什么意思?

转载 作者:太空宇宙 更新时间:2023-11-04 10:00:51 26 4
gpt4 key购买 nike

在LDD3(Linux Device Drivers 3rd Edition book)scullpipe中,static int scull_read_p_mem(char *buf, char **start, off_t offset, int count, int *eof, void *data) 是什么意思?具体来说,我不明白startpageoffset 之间的区别。

关于实际实现本身(可以在下面找到)我有很多问题:

struct scull_pipe {
wait_queue_head_t inq, outq; /* read and write queues */
char *buffer, *end; /* begin of buf, end of buf */
int buffersize; /* used in pointer arithmetic */
char *rp, *wp; /* where to read, where to write */
int nreaders, nwriters; /* number of openings for r/w */
struct fasync_struct *async_queue; /* asynchronous readers */
struct semaphore sem; /* mutual exclusion semaphore */
struct cdev cdev; /* Char device structure */
};

int scull_p_nr_devs; /* the number of scull_pipe devices */
scull_pipe *scull_p_devices; /* scull_pipe devices to be malloc'ed */

/* ...... */

/* our proc read implementation */
static int scull_read_p_mem(char *buf, char **start, off_t offset, int count,
int *eof, void *data)
{
int i, len;
struct scull_pipe *p;

#define LIMIT (PAGE_SIZE-200) /* don't print any more after this size */
*start = buf;
len = sprintf(buf, "Default buffersize is %i\n", scull_p_buffer);
for(i = 0; i < scull_p_nr_devs && len <= LIMIT; i++) {
p = &scull_p_devices[i];
if (down_interruptible(&p->sem))
return -ERESTARTSYS;
len += sprintf(buf+len, "\nDevice %i: %p\n", i, p);
len += sprintf(buf+len, " Buffer: %p to %p (%i bytes)\n",
p->buffer, p->end, p->buffersize);
len += sprintf(buf+len, " rp %p wp %p\n", p->rp, p->wp);
len += sprintf(buf+len, " readers %i writers %i\n",
p->nreaders, p->nwriters);
up(&p->sem);
scullp_proc_offset(buf, start, &offset, &len);
}
*eof = (len <= LIMIT);
return len;
}


static void scullp_proc_offset(char *buf, char **start, off_t *offset, int *len)
{
/* QUESTION: what does this function do? */
if (*offset == 0)
return;
if (*offset >= *len) {
*offset -= *len; /* QUESTION: what is the purpose of this? */
*len = 0;
}
else {
*start = buf + *offset; /* QUESTION: why do you need to change "start"? */
*offset = 0;
}
}

最佳答案

函数scull_read_p_mem用于创建 proc 条目 here使用 create_proc_read_entry功能。 5 分钟的谷歌搜索给出了 this page其中解释了传递给 create_proc_read_entry 函数的函数指针中的参数。固定格式是 sais:

Arguments:
*buf : The kernel allocates a page of memory to any process that attempts to read a proc entry. The page pointer points to that buffer of memory into which the data is written.
**start: This pointer is used when the reading of the proc file should not start from the beginning of the file but from a certain offset. For small reads this is generally set to NULL.
off : The offset from the beginning of the file where the file pointer currently points to
count : The number of bytes of data to be read
data : The data passed from the create_read_proc_entry function call.
eof: is set to 1 to indicate end of file

但过了一段时间我还在 kenel fs/proc/generic.c 中找到了一些文档.它有点长,但我认为这是总结 start 参数的唯一来源:

        /*
* How to be a proc read function
* ------------------------------
* Prototype:
* int f(char *buffer, char **start, off_t offset,
* int count, int *peof, void *dat)
*
* Assume that the buffer is "count" bytes in size.
*
* If you know you have supplied all the data you
* have, set *peof.
*
* You have three ways to return data:
* 0) Leave *start = NULL. (This is the default.)
* Put the data of the requested offset at that
* offset within the buffer. Return the number (n)
* of bytes there are from the beginning of the
* buffer up to the last byte of data. If the
* number of supplied bytes (= n - offset) is
* greater than zero and you didn't signal eof
* and the reader is prepared to take more data
* you will be called again with the requested
* offset advanced by the number of bytes
* absorbed. This interface is useful for files
* no larger than the buffer.
* 1) Set *start = an unsigned long value less than
* the buffer address but greater than zero.
* Put the data of the requested offset at the
* beginning of the buffer. Return the number of
* bytes of data placed there. If this number is
* greater than zero and you didn't signal eof
* and the reader is prepared to take more data
* you will be called again with the requested
* offset advanced by *start. This interface is
* useful when you have a large file consisting
* of a series of blocks which you want to count
* and return as wholes.
* (Hack by Paul.Russell@rustcorp.com.au)
* 2) Set *start = an address within the buffer.
* Put the data of the requested offset at *start.
* Return the number of bytes of data placed there.
* If this number is greater than zero and you
* didn't signal eof and the reader is prepared to
* take more data you will be called again with the
* requested offset advanced by the number of bytes
* absorbed.
*/

我们可以see稍后在 copy_to_user 中使用的 start - 该参数用于优化对 biiiig 文件的 proc 条目读取。用户可以传递非常小的 count 变量,但是您有很大的文件要读取。因此,您使用 *start 参数从 proc read 函数返回该文件的大小,该参数表示要读取的字节数。这样内核甚至可以传递 count=0,但是 proc_read 函数可以像 5000 一样返回一个有效的 *start 地址,稍后会在 copy_to_user 调用中使用以加快读取速度。

所以:

what do the parameters in static int scull_read_p_mem(char *buf, char **start, off_t offset, int count, int *eof, void *data) mean?

  • buf - 将结果复制到的目标缓冲区
  • start - 上面注释中解释的魔法指针用于加速 proc 读取。
  • offset - 要读取的文件中的偏移量
  • count - 要读取的字节数
  • eof - 一个指向 int 的指针,需要设置为非零值,以防读取整个文件
  • data - 用户上下文,作为 create_proc_entry 函数中的最后一个参数传递。

There are a number of questions I have regarding the actual implementation itself (which can be found below):

scullp_proc_offset 操作 buf 缓冲区内的 len 偏移量。如果offset != 0,那么scull_read_p_mem 不需要从第一个字节开始读取,而是一些字节offset。因为它是延迟写入的,所以 snprintf 调用无论如何都会执行,您需要“某种程度的转移”缓冲区。

此函数的作用是什么? - 事实上,我认为这是一种计算有多少字节被/需要复制给用户的有趣方式。

这样做的目的是什么? - 不知道。看起来有问题,因为 *offset 会变成负值。函数 /* FIXME this should use seq_file */ 上面的注释说还有一些东西需要修复。我认为 ides 在一次调用中返回关于一个 scull_p_devices[i] 的准确信息。

为什么需要更改“开始”? - 就是这样。如果 *offset 与 0 不同,并且如果我们有一些字节要读取,我们应该返回一个指向 buf + offset 的指针,让内核知道从哪里读取。请注意,*start = buf 已经初始化,因此内核将执行 copy_to_user(... *start, len)

关于c - scull 的 proc read 实现中的参数是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56333180/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com